【发布时间】:2018-05-18 06:39:40
【问题描述】:
我在一段代码中看到了这行代码,想知道它的用途
var item = new List<int>.Enumerator();
这是做什么的?
【问题讨论】:
-
@Dr.Snail 我已更正并删除了评论
标签: c# list enumerator
我在一段代码中看到了这行代码,想知道它的用途
var item = new List<int>.Enumerator();
这是做什么的?
【问题讨论】:
标签: c# list enumerator
这是一个非常无用和错误的东西......
第一个问题应该是List<T>.Enumerator是什么...它是List<T>的一个支持类,它实现了IEnumerator<T>接口(用于枚举集合的接口,例如foreach使用的)。 For performance reasons it is a struct instead of being a class。作为struct 具有预定义的公共无参数构造函数(您正在使用的构造函数)。它甚至还有一个internal 构造函数,它带有一个参数(List<T> list),用于设置一些必要的内部字段(最重要的是对创建它的List<> 的引用)。这个构造函数被List<>.GetEnumerator()使用。
现在,如果你按照你写的去做,你会创建一个“不完整的”Enumerator。 item.Current 将“工作”(返回default(T)),但如果您尝试执行item.MoveNext(),您将得到NullReferenceException。如果您想要一个“空”集合的IEnumerator,最好这样做:
var item = Enumerable.Empty<int>().GetEnumerator();
因为List<T>.Enumerator 是public 而不是private 或internal 的原因...有点复杂。 List<T> 实现了IEnumerable<T> 和IEnumerable,所以它必须至少有两个带有这些签名的方法:
IEnumerator<T> IEnumerable<T>.GetEnumerator()
和
IEnumerator IEnumerable.GetEnumerator()
但出于性能原因,它将它们实现为显式实现(因此隐藏它们),并实现第三种方法:
public Enumerator GetEnumerator()
返回struct Enumerator... 现在,感谢foreach 的工作方式,这第三个公共方法将是foreach 使用的方法。为什么这个?因为通过其接口之一使用的struct(在这种情况下为IEnumerator<T> 或IEnumerator)被装箱(这会稍微减慢它的速度)......但是如果直接使用struct(通过它的@987654357 @) 方法,没有装箱,性能稍微好一点...微软程序员在List<> 性能上给出了110% :-)
【讨论】:
所以var item = new List<int>.Enumerator(); 返回Enumerable 结构的实例,它将映射到您的列表。由于 Enumerator 是结构,它将使用默认值初始化其成员,在这种情况下,基于代码它将列表初始化为 null。详情可以看code of list.
在这种情况下,不存在列表实例,所以如果您访问这样的任何方法
var item = new List<int>.Enumerator();
item.Currnet or item.MovNext()
主要抛出异常或默认 int 你必须尝试一下。
详情:https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
{
private List<T> list;
private int index;
private int version;
private T current;
internal Enumerator(List<T> list) {
this.list = list;
index = 0;
version = list._version;
current = default(T);
}
public void Dispose() {
}
public bool MoveNext() {
List<T> localList = list;
if (version == localList._version && ((uint)index < (uint)localList._size))
{
current = localList._items[index];
index++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare()
{
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = list._size + 1;
current = default(T);
return false;
}
【讨论】: