GetIterator()和迭代器模式

时间:2013-08-28 21:16:19

标签: c# iterator ienumerable ienumerator

我试图实现迭代器模式。 基本上从我的理解,它使一个类“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”只返回一个部分或一个匿名对象。   如果没有,那么正确的方法是什么..

1 个答案:

答案 0 :(得分:4)

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

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#Programming Language 3rd”中的注释,第369页:

  

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

     

foreach (int x in myIntCollection)

     

没有泛型而没有拳击。整齐。