foreach
语句为数组中的每个元素或实现System.Collections.IEnumerable
或System.Collections.Generic.IEnumerable<T>
接口的对象集合重复一组嵌入式语句。
我理解如果我们想在对象集合上使用foreach,我们需要在其上实现IEnumerable。
我想了解IEnumerable中的实现如何启用'foreach'的使用?
IEnumerable的源代码似乎只有一个函数'GetEnumerator',显然没有实现,因为IEnumerable是一个接口 - 那么foreach关键字如何实际使用IEnumerable接口进行枚举?
修改: 在这种情况下也试图理解它:
IEnumerable<Int> myNumbers = new IEnumerable<Int>();
这里调用/使用哪个GetEnumerator()?
编辑2:
所以答案似乎是:
1:DuckTyping - (感谢@Alexei Levenkov。我接受@horrorcat作为答案,因为我只能接受一个:))
2.我试图创建一个接口的具体实例(在我的问题的第二部分)中犯了一个明显的错误 - (感谢@Gary Vass)
答案 0 :(得分:1)
foreach
调用IEnumerable.GetEnumerator()
(如果集合实现了一个)或查找返回duck-typed matching iterator class的GetEnumerator()
方法。
使用GetEnumerator()
调用的结果迭代元素,将每个元素转换为foreach
的第一个参数中指定的类型。
答案 1 :(得分:1)
IEnumerable.GetEnumerator()返回一个枚举器对象(实现IEnumerator)。它有一个返回当前项的属性“Current”,以及一个方法“MoveNext()”,它将枚举器推进到下一个项目。
这是执行foreach所需的所有foreach循环。它只是将“Current”属性赋给变量,然后每次执行.MoveNext()。
通常,当您在类上实现IEnumerable时,您知道源的来源。所以,如果你有一个像这样的课程
public class MyEnumerable
{
private List<string> items;
}
IEnumerable的实现看起来像这样
public class MyEnumerable : IEnumerable<string>
{
private List<string> items;
public IEnumerator<string> GetEnumerator()
{
return items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return items.GetEnumerator();
}
}
请注意,枚举器来自列表对象,因此您不必担心创建枚举器(尽管您可以通过实现IEnumerator来实现)
答案 2 :(得分:0)
正如Lukazoid所说:“IEnumerable的实现者实现了方法GetEnumerator(),foreach调用此方法,然后使用生成的IEnumerator迭代元素。”
foreach
仅使用接口IEnumerable / IEnumerable&lt;&gt;,我认为这是用于编写'readonly'for循环的C#快捷方式,您可以使用该数据但不能编辑它。
我也发现了这一点,这里是stackoverflow //which may make this question a dup
答案 3 :(得分:0)
Foreach只是使用IEnumerable类型的语法糖。代码如:
foreach (var item in collection)
{
...
}
由编译器翻译为:
using (var enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// loop contents here
}
}