質問

このコード(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 (この場合は反復変数)のコピーでのみ動作します。

構造体は値型ですが、クラスは参照型です。これが、これがクラスであるときにコンパイルされるのですが、構造体ではないときにコンパイルされる理由です

詳細: http://www.albahari.com/valuevsreftypes.aspx

@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は、設定できるプロパティがないため、実際には非常に悪い例ですが、画像を取得します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top