我最近一直在阅读有关延迟执行、LINQ、一般查询等的文章和文档,以及"对象是枚举的"这一短语。经常出现。有人能解释一下当对象被枚举时会发生什么吗?
文章示例。
这个方法通过延迟执行实现。立即返回值是一个对象,它存储执行操作所需的所有信息。在对象被枚举之前,此方法表示的查询不会执行。要么直接调用它的GetEnumerator方法,要么在Visual c#中使用foreach
枚举的一般说明
IEnumerable
是一个接口,在c#中通常由集合类型实现。例如:List
、Queue
、Array
。
IEnumerable
提供了一个方法GetEnumerator
,它返回一个类型为IEnumerator
的对象。
IEnumerator
基本上代表了一个"向前移动指针"。到集合中的元素。IEnumerator
有:
- 属性
Current
,返回当前指向的对象(例如集合中的第一个对象)。 - 一个方法
MoveNext
,它将指针移动到下一个元素。调用它之后,Current
将保存对集合中下一个对象的引用。如果集合中没有其他元素,MoveNext
将返回false
。
每当在IEnumerable
上执行foreach
循环时,通过GetEnumerator
检索IEnumerator
,并在每次迭代中调用MoveNext
,直到最终返回false
。在循环头文件中定义的变量,用IEnumerator
的Current
填充。
编译foreach循环
感谢@Llama
这段代码…
List<int> a = new List<int>();
foreach (var val in a)
{
var b = 1 + val;
}
被编译器转换成这样:
List<int> list = new List<int>();
List<int>.Enumerator enumerator = list.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
int current = enumerator.Current;
int num = 1 + current;
}
} finally {
((IDisposable)enumerator).Dispose();
}
"
例如,只要将对象放入这个方法表示的查询直到对象通过直接调用其GetEnumerator方法或在Visual c#中使用foreach
foreach
循环中,就会自动调用GetEnumerator
。当然,其他函数,例如Linq查询,也可以通过显式(调用GetEnumerator
)或在某种循环中隐式地从集合中检索IEnumerator
,就像我在上面的示例中所做的那样。
我认为你只需要很好地理解LINQ查询的延迟执行和立即执行。
延迟执行当你写一个LINQ查询时,它只在你实际访问结果时执行——延迟到你运行代码迭代,即在结果上使用foreach
。这是默认行为。
立即执行:我们可以通过在查询中附加ToList()
或类似的方法来强制执行(这在c#代码中经常会看到)。