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";。如果没有,正确的方法是什么。。。

GetIterator()和迭代器模式

首先是一个较小且简化的自包含版本:

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()是如何生成实现CurrentMoveNext的东西的呢?来自同一部分:

迭代器是一个语句块,它产生一个有序的值序列。迭代器与正常语句块的区别在于存在一个或多个yield语句

重要的是要理解迭代器不是一种成员,而是实现函数成员的一种方法

因此,方法的主体是迭代器块,编译器检查许多约束(该方法必须返回IEnumerable或IEnumerator),然后为您实现IEnumerator成员。

而更深层的";为什么";,我也学到了一些东西。根据Eric Lippert在";C#编程语言3rd";,第369页:

这被称为";基于模式的方法";它可以追溯到仿制药之前。C#1中基于接口的方法完全基于传递object,并且值类型总是必须装箱。模式方法允许

foreach (int x in myIntCollection)

没有泛型,也没有装箱。整洁的