如果我用C#编写一个foreach语句:
foreach(String a in veryComplicatedFunction())
{
}
它会在每次迭代时计算非常复杂的函数还是仅计算一次,并将其存储在某处?
答案 0 :(得分:38)
您的问题由规范的第8.8.4节回答,其中指出:
以上步骤,如果成功, 毫不含糊地制作一个系列 类型C,枚举器类型E和元素 类型T.一个foreach语句 形式
foreach (V v in x) embedded-statement
然后扩展为:
{
E e = ((C)(x)).GetEnumerator();
try {
V v;
while (e.MoveNext()) {
v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
如您所见,在扩展中,表达式x仅被评估一次。
答案 1 :(得分:18)
它只会计算一次
答案 2 :(得分:6)
这取决于你的意思。如果您有类似以下的方法:
public static IEnumerable<int> veryComplicatedFunction()
{
List<string> l = new List<string> { "1", "2", "3" };
foreach (var item in l)
{
yield return item;
}
}
每次产生后,控制权将返回到调用veryComplicatedFunction的方法。因此,如果他们共享List l,那么你可能会得到一些奇怪的结果。消除这类问题的一种可靠方法是调用veryComplicatedFunction上的ToArray扩展。
答案 3 :(得分:5)
veryComplicatedFunction
可能会返回IEnumerable<string>
,这意味着它的计算只执行一次,并以某种方式汇总其结果。但是,如果没有看到实际的方法,就无法保证它的作用。保证的是veryComplicatedFunction
只被调用一次,foreach
所做的是迭代方法的返回。
答案 4 :(得分:1)
它应该只计算一次。作为旁注,非常复杂的函数()必须返回IEnumerable
或IEnumerable<T>
或任何具有公共GetEnumerator()方法的对象。
答案 5 :(得分:0)
如果每次计算它,如果你的功能是基于动态的东西,如当前时间,它可能会引起痛苦的世界。它应该计算一次。