Foreach Cache IEnumerable吗?

时间:2011-07-14 08:20:37

标签: c# ienumerable

假设SomeMethod有签名

public IEnumerable<T> SomeMethod<T>();

之间有什么区别
foreach (T tmp in SomeMethod<T>()) { ... }

IEnumerable<T> result = SomeMethod<T>();

foreach (T tmp in result) { ... }

换句话说,SomeMethod<T>的结果会缓存在第一个语句上还是会在每次迭代时进行评估?

2 个答案:

答案 0 :(得分:13)

假设你在谈论C#。

foreach会转换为以下内容:

var enumerable = SomeMethod<T>(); // Or whatever is passed to foreach
var enumerator = enumerable.GetEnumerator();

while (enumerator.MoveNext())
{
...
}

因此,由于enumerable只需要一次,因此即使您将其直接放入foreach语句,也只会调用一次SomeMethod。

答案 1 :(得分:0)

enumerATOR通常是与enumerable不同类型的对象。通常,枚举器将保存对可枚举对象的引用,以及有关枚举过程中的位置的一些信息。可枚举对象的目的实际上并不是提供一系列项目,而是提供一个枚举器,该枚举器将依次提供序列。

在vb.net和C#中,foreach构造通过在对象上调用GetEnumerator方法一次并抓取它返回的对象,在GetEnumerator返回的对象上重复调用MoveNext和Current,最后,如果该对象实现处理,调用Dispose。 C#和vb.net都没有实际缓存可枚举对象,但是在它上面调用GetEnumerator之后,它们都不需要将对象用于任何目的。两种语言都保留在枚举器上,但除了对MoveNext,Current和Dispose的隐含调用之外,它们都没有提供任何使用它的方法。