我正在查看IEnumerable
并尝试this链接中给出的示例。我理解当我们使用foreach
进行迭代时,GetEnumerator()
方法会被调用,因为我的List
类已经实现了IEnumerable(或者可能是我错了)。
public class List<T> : IEnumerable
{
private T[] _collection;
public List(T[] inputs)
{
_collection = new T[inputs.Length];
for (int i = 0; i < inputs.Length; i++)
{
_collection[i] = inputs[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public CollectionEnum<T> GetEnumerator()
{
return new CollectionEnum<T>(_collection);
}
}
public class CollectionEnum<T> : IEnumerator
{
public T[] _collection ;
int position = -1;
public CollectionEnum(T[] list)
{
_collection = list;
}
public bool MoveNext()
{
position++;
return (position < _collection.Length);
}
//implementation on Current and Reset
}
然后,还提到使用IEnumerable
进行迭代不需要foreach
的实现。因此,在上面的代码中,如果删除IEnumerable
的实现,则foreach
必须正常工作。所以我的List<>
课程看起来像
public class List<T>
{
private T[] _collection;
public List(T[] persons)
{
_collection = new T[persons.Length];
for (int i = 0; i < persons.Length; i++)
{
_collection[i] = persons[i];
}
}
public CollectionEnum<T> GetEnumerator()
{
return new CollectionEnum<T>(_collection);
}
}
哪个确实有效。现在我不明白foreach
如何知道我的班级有一个方法调用GetEnumerator()
,它返回一个IEnumerator
类型。
答案 0 :(得分:2)
如果您的收藏集未实现
IEnumerable
,您仍必须 通过提供a来遵循迭代器模式来支持这种语法GetEnumerator
方法,返回接口,类或结构 ....包含当前属性, MoveNext 和重置方法为 由IEnumerator
描述,但该类不必实现IEnumerator
。
答案 1 :(得分:1)
正如Nkosi所提到的,在解释foreach时,编译器会查找最初在IEnumerable和IEnumerator中表示的模式。
早期版本的C#编译器需要实现这些接口。但是,随着LINQ的出现,语言和编译器已经过调整,可以更好地识别模式。
例如,您可以围绕具有Where方法但不实现IEnumerable的对象创建LINQ查询。
同样,您可以等待Awaitable Pattern之后的任何对象,而不仅仅是Task或Task。
一旦你理解了编译器正在寻找满足模式的特定方法,就会更容易理解为什么foreach不需要IEnumerable。还要记住,foreach实际上只是遍历一组对象的语法糖。