11

検証メソッドを実行するための簡単なテストを行っていたところ、この奇妙な状況に遭遇しました。

public IEnumerable<int> ints (List<int> l)
{
 if(false)yield return 6;
 l.Add(4);
}


void Main()
{
 var a = new List<int>();
 var b = new List<int>();
 for( int i = 0; i < 4; i++ ){
  a.Add(i);
  b.Add(i);
 }
 a.AddRange(ints(a));
 ints(b);
 Console.WriteLine(a);
 Console.WriteLine(b);
}

このコードが実行されると、aが含まれます[0,1,2,3,4]。ただし、bが含まれます[0,1,2,3]。メソッドを引数として呼び出すとAddRange、リストを参照渡しできるのはなぜですか? または、それが起こらなかった場合、何が起こったのですか?

4

1 に答える 1

15

ints(b)呼び出しは enumerate ではないため、すべてのアイテムを列挙してリストに追加する場合とは異なり、IEnumerableコードが行に到達することはありません。l.Add(4)AddRange

bcase enumerate 結果を手動で呼び出したことを確認するには、次のようにします。

ints(b).ToList();

IEnumerable<T>関数を介して実装された関数は、列挙が開始される前に関数の本体を実行していません-コードは実際にはコンパイラによって、列挙可能な真の遅延評価をサポートする状態を持つクラスに変換されます (詳細は、複数の記事で見つけることができますシュメルター)。

于 2013-06-26T21:13:24.167 に答える