質問
このコード(C#)があります:
using System.Collections.Generic;
namespace ConsoleApplication1
{
public struct Thing
{
public string Name;
}
class Program
{
static void Main(string[] args)
{
List<Thing> things = new List<Thing>();
foreach (Thing t in things) // for each file
{
t.Name = "xxx";
}
}
}
}
コンパイルしません。
エラー:
Cannot modify members of 't' because it is a 'foreach iteration variable'
Thing
を struct
ではなく class
に変更した場合、コンパイルは実行されます。
誰かが何が起こっているのか説明してもらえますか?
解決
多かれ少なかれ、コンパイラはforeachのループ変数(の一部)を変更させません。
単に使用:
for(int i = 0; i < things.Count; i+= 1) // for each file
{
things[i].Name = "xxx";
}
そして、それは Thing
がクラスの場合に機能します。ループ変数は参照であり、参照自体ではなく、参照されたオブジェクトにのみ変更を加えるからです。
他のヒント
構造体は参照型ではなく、値型です。
Thing
の struct
の代わりに class
を使用する場合、foreachループは参照変数を作成します。リスト内の正しい要素を指します。ただし、値型であるため、 Thing
(この場合は反復変数)のコピーでのみ動作します。
構造体は値型ですが、クラスは参照型です。これが、これがクラスであるときにコンパイルされるのですが、構造体ではないときにコンパイルされる理由です
@Henkのソリューションで好む代替構文はこれです。
DateTime[] dates = new DateTime[10];
foreach(int index in Enumerable.Range(0, dates.Length))
{
ref DateTime date = ref dates[index];
// Do stuff with date.
// ...
}
ループ内で適切な量の作業を行っている場合は、どこからでもインデックス作成を繰り返す必要がなくなります。
PS DateTimeは、設定できるプロパティがないため、実際には非常に悪い例ですが、画像を取得します。
所属していません StackOverflow