为什么使用 foreach 迭代时不需要实现 IEnumerable
本文关键字:不需要 实现 IEnumerable 迭代 foreach 为什么 | 更新日期: 2023-09-27 18:37:28
我正在研究IEnumerable
并尝试此链接中给出的示例。我知道当我们使用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
怎么知道我的类有一个返回IEnumerator
类型的方法调用GetEnumerator()
。
您链接到的文章已经在备注中为您提供了解释。
如果您的集合未实现
IEnumerable
,则仍必须 遵循迭代器模式,通过提供GetEnumerator
返回接口、类或结构的方法。包含当前属性,以及 MoveNext 和重置方法为 由IEnumerator
描述,但类不必实现IEnumerator
.
正如 Nkosi 所提到的,在解释 foreach 时,编译器会寻找最初在 IEnumerable 和 IEnumerator 中表示的模式。
早期版本的 C# 编译器需要实现这些接口。 但是,随着 LINQ 的出现,语言和编译器已进行调整,以执行更多识别模式的操作。
例如,可以围绕具有 Where 方法但不实现 IEnumerable 的对象创建 LINQ 查询。
同样,您可以等待遵循可等待模式的任何对象,而不仅仅是任务或任务。
一旦你理解了编译器正在寻找的特定方法来满足某种模式,就更容易理解为什么 foreach 不需要 IEnumerable。 还要记住,foreach 实际上只是用于遍历对象集合的语法糖。