使用枚举器实例化列表

Instantiation of List with Enumerator

我在代码片段中看到了这一行,想知道它的用途

var item = new List<int>.Enumerator();

这是做什么的?

我去编码了解更多,这就是我发现的

所以 var item = new List<int>.Enumerator(); return 您 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;                
            }

这是非常无用和错误的东西...

第一个问题应该是List<T>.Enumerator是什么...它是List<T>的一个支持class实现了IEnumerator<T>接口(用于枚举一个集合,例如 foreach)。 For performance reasons it is a struct instead of being a class。作为 struct 有一个预定义的 public 无参数构造函数(您正在使用的构造函数)。它甚至有一个带有一个参数 (List<T> list) 的 internal 构造函数,用于设置一些必要的内部字段(最重要的是对创建它的 List<> 的引用)。此构造函数由 List<>.GetEnumerator().

使用

现在,如果你按照你写的去做,你将创建一个 "incomplete" Enumeratoritem.Current 将 "work"(返回 default(T)),但如果您尝试执行 item.MoveNext(),您将得到 NullReferenceException。如果你想要 IEnumerator 用于 "empty" 集合,最好这样做:

var item = Enumerable.Empty<int>().GetEnumerator();

为什么List<T>.Enumeratorpublic而不是privateinternal... 有点复杂。 List<T> 实现了 IEnumerable<T>IEnumerable,因此它必须至少有两个具有这些签名的方法:

IEnumerator<T> IEnumerable<T>.GetEnumerator()

IEnumerator IEnumerable.GetEnumerator()

但出于性能原因,它将它们实现为显式实现(因此隐藏它们),并实现第三种方法:

public Enumerator GetEnumerator()

那个 returns 一个 struct Enumerator...现在,由于 foreach 的工作原理,这第三个 public 方法将成为 foreach.为什么这个?因为通过其接口之一使用的 struct(在本例中为 IEnumerator<T>IEnumerator)被装箱(这会减慢它的速度)...但是如果 struct直接使用(通过其public Enumerator GetEnumerator())方法,没有装箱,性能好一点......微软程序员在List<>性能上付出了110%:-)