假设SomeMethod
有签名
public IEnumerable<T> SomeMethod<T>();
之间有什么区别
foreach (T tmp in SomeMethod<T>()) { ... }
和
IEnumerable<T> result = SomeMethod<T>();
foreach (T tmp in result) { ... }
换句话说,SomeMethod<T>
的结果会缓存在第一个语句上还是会在每次迭代时进行评估?
答案 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的隐含调用之外,它们都没有提供任何使用它的方法。