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)call 不枚举IEnumerable,因此代码永远不会到达l.Add(4)行,AddRange这与枚举所有项目以将它们添加到列表中的情况不同。

要查看它需要b手动枚举结果:

ints(b).ToList();

IEnumerable<T>通过函数实现在枚举开始之前不执行函数体 - 代码实际上由编译器转换为具有状态的类,以支持对可枚举的真正惰性求值(详细信息可以在多篇文章中找到,即Iterator Pattern demystified - Tim 提供的链接施梅尔特)。

于 2013-06-26T21:13:24.167 回答