Ida*_*ana 2 c# ienumerable ienumerator iterator
我正在尝试实现迭代器模式。基本上,据我所知,它使类成为“foreachble”,并通过不向用户透露确切的集合类型来使代码更安全。
我一直在试验,我发现如果我在我的类中实现 IEnumerator GetEnumerator(),我得到了想要的结果......似乎可以省去搞乱实现接口的麻烦。
这是我的意思的一瞥:
public class ListUserLoggedIn
{
/*
stuff
*/
public List<UserLoggedIn> UserList { get; set; }
public IEnumerator<UserLoggedIn> GetEnumerator()
{
foreach (UserLoggedIn user in this.UserList)
{
yield return user;
}
}
public void traverse()
{
foreach (var item in ListUserLoggedIn.Instance)
{
Console.Write(item.Id);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想我的问题是,这是迭代器的有效示例吗?如果是,为什么这是有效的,我该怎么做才能使迭代器通过“var”仅返回一部分或匿名对象。如果不是,正确的方法是什么...
首先是一个更小和简化的独立版本:
class Program
{
public IEnumerator<int> GetEnumerator() // IEnumerable<int> works too.
{
for (int i = 0; i < 5; i++)
yield return i;
}
static void Main(string[] args)
{
var p = new Program();
foreach (int x in p)
{
Console.WriteLine(x);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的“奇怪”之处在于class Program没有实现IEnumerable.
Ecma-334 的规范说:
§ 8.18 迭代器
foreach 语句用于迭代可枚举集合的元素。为了可枚举,集合应具有返回枚举器的无参数 GetEnumerator 方法。
所以这就是为什么foreach()在你的课堂上工作的原因。没有提到 IEnumerable。但是 GetEnumerator() 如何产生实现Currentand 的东西MoveNext?来自同一部分:
迭代器是产生有序值序列的语句块。迭代器与普通语句块的区别在于是否存在一个或多个 yield 语句
重要的是要理解迭代器不是一种成员,而是实现函数成员的一种方式
所以你的方法的主体是一个迭代器块,编译器检查一些约束(该方法必须返回一个 IEnumerable 或 IEnumerator),然后IEnumerator为你实现成员。
对于更深层次的“为什么”,我也学到了一些东西。基于 Eric Lippert 在“The C# Programming Language 3rd”,第 369 页中的注释:
这被称为“基于模式的方法”,它可以追溯到泛型之前。C#1 中基于接口的方法将完全基于传递
object,并且值类型总是必须被装箱。模式方法允许
foreach (int x in myIntCollection)没有泛型和拳击。整洁的。