GetIterator()和迭代器模式
本文关键字:迭代器 模式 GetIterator | 更新日期: 2023-09-27 18:29:20
我正在尝试实现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);
}
}
}
我想我的问题是,这是迭代器的一个有效例子吗?如果是,为什么这样做,以及我能做些什么让迭代器通过"只返回一部分或一个匿名对象;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);
}
}
}
这里"奇怪"的是class Program
没有实现IEnumerable
。
Ecma-334的规格是:
§8.18迭代
foreach语句用于迭代可枚举集合的元素。为了可枚举,集合应具有返回枚举器的无参数GetEnumerator方法。
所以这就是foreach()
在你的课上起作用的原因。没有提到IEnumerable。但是GetEnumerator()是如何生成实现Current
和MoveNext
的东西的呢?来自同一部分:
迭代器是一个语句块,它产生一个有序的值序列。迭代器与正常语句块的区别在于存在一个或多个yield语句
重要的是要理解迭代器不是一种成员,而是实现函数成员的一种方法
因此,方法的主体是迭代器块,编译器检查许多约束(该方法必须返回IEnumerable或IEnumerator),然后为您实现IEnumerator
成员。
而更深层的";为什么";,我也学到了一些东西。根据Eric Lippert在";C#编程语言3rd";,第369页:
这被称为";基于模式的方法";它可以追溯到仿制药之前。C#1中基于接口的方法完全基于传递
object
,并且值类型总是必须装箱。模式方法允许
foreach (int x in myIntCollection)
没有泛型,也没有装箱。整洁的