checkpoint

自分用のIT技術系ノートです。古い情報や間違っている情報もあるので注意。

foreachと構造体

.NETの構造体は値型。これ基本。
しかし油断しているとつい下記のようなことをしてしまう。


//構造体
public struct ExampleStruct
{
 public int Number
 {
  //get,set...
 }
 private int number;
}

//構造体利用側
...
private ExampleStruct[] exstrArray = new ExampleStruct[10];
//中略
int i = 0;
foreach(ExampleStruct exstr in exstrArray)
{
 exstr.Name = i;
 i++;
}
...

このコードは一見何の問題もないように見えるが、
実際はビルドの時に以下のメッセージと共に蹴られる。

代入式の左辺には変数、プロパティ、またはインデクサを指定しください。

プロパティですが、何か?という感じだが、
foreach内の"exstr"は、実はexstrArray内要素のコピーになる。
構造体は値型であるが故、上記"exstr"とexstrArray内要素は
関係のない全くの赤の他人なのだ。


で、.NETのコンパイラは(親切なことに)無駄な操作に対して
「何やってんの?」とエラーを出してくれるというワケ。


これはforeachのときだけでなく下記のような場合にも起こる。


public class ExampleClass
{
 //中略
 //前述の構造体
 public ExampleStruct ExStr
 {
  //get,set...
 }
 private ExampleStruct exstr = new ExampleStruct();
}


//ExampleClass利用側
...
 private ExampleClass excls = new ExampleClass();
 excls.ExStr.Number = 1;
...


これもビルド時に下記のエラーメッセージと共に蹴られる。

変数ではないため、'ExampleClass.ExStr' の戻り値を変更できません。


理由はforeachの時と同じ。プロパティのgetアクセサの時点で、
取得されるのはExampleClassクラスメンバのexstrではなく、
そのコピーだからだ。


当然のことながら、参照型であるクラスの場合にはこのような
現象は起こらない。


構造体は使いどころが難しいなあ。