I've seen this line in a code snipped and was wondering of the use of it
var item = new List<int>.Enumerator();
What does this do?
I've seen this line in a code snipped and was wondering of the use of it
var item = new List<int>.Enumerator();
What does this do?
It is something quite useless and wrong...
The first question should be what is the List<T>.Enumerator
... It is a support class of List<T>
that implements the IEnumerator<T>
interface (the interface used for enumerating a collection, used for example by the foreach
). For performance reasons it is a struct
instead of being a class
. Being a struct
is has a predefined public parameterless constructor (the one you are using). It has even an internal
constructor with one parameter (List<T> list
) that sets some necessary internal fields (the most important is a reference to the List<>
that created it). This constructor is used by List<>.GetEnumerator()
.
Now, if you do what you wrote, you will create an "incomplete" Enumerator
. The item.Current
will "work" (returning a default(T)
) but if you try to do a item.MoveNext()
you'll get a NullReferenceException
. If you want an IEnumerator
for an "empty" collection, it would be better to do:
var item = Enumerable.Empty<int>().GetEnumerator();
For the reason why List<T>.Enumerator
is public
instead of being private
or internal
... It is a little more complex. List<T>
implements IEnumerable<T>
and IEnumerable
, so it must have at least two methods with these signatures:
IEnumerator<T> IEnumerable<T>.GetEnumerator()
and
IEnumerator IEnumerable.GetEnumerator()
but for performance reasons it implements them as explicit implementation (so hiding them), and implements a third method:
public Enumerator GetEnumerator()
that returns a struct Enumerator
... now, thanks to how foreach
works, this third public method will be the one used by foreach
. Why this? Because a struct
used through one of its interfaces (IEnumerator<T>
or IEnumerator
in this case) is boxed (something that slows it a little)... but if the struct
is used directly (through its public Enumerator GetEnumerator()
) method, there is no boxing and the performance is a little better... Microsoft programmers gave their 110% on List<>
performances :-)
I went to code to find out more , This is what i found
so var item = new List<int>.Enumerator();
return you instance of Enumerable
structure , which is going to map to your list. As Enumerator is structure it will initialize its member with default value , in this case based on code it will initialize list to null. for detail you can see code of list.
In this case there is no list instance exist , so if you access any method like this
var item = new List<int>.Enumerator();
item.Currnet or item.MovNext()
throws exception mostly or default int you have to tried that out.
In detail : 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;
}