为什么我们需要IEnumerator和IEnumerable?

时间:2012-12-16 14:36:19

标签: c# .net ienumerable ienumerator

好的,我刚刚完成了IEnumeratorIEnumerable。现在MSDN说这些东西的主要目标是遍历客户集合。

足够公平但我能够在不使用任何一个的情况下迭代自定义集合(或者至少我想这么认为)

namespace ienumerator
{

class person
{
    public person(string first, string second)
    {
        fname = first;
        lname = second;
    }
    public string fname { get; set; }
    public string lname { get; set; }
}

class person_list
{
    public person[] list;
    public person_list(person[] per)
    {
        list = new person[per.Length];
        for (int i = 0; i < per.Length; i++)
        {
            list[i] = per[i];
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        person[] names = new person[3]
        {
            new person("some","one"),
            new person("another","one"),
            new person("sss","ssdad"),
        };

        person_list list_of_names = new person_list(names);
        int i = 0;
        while (i < list_of_names.list.Length)
        {
            Console.WriteLine(list_of_names.list[i].fname);
            i++;
        }
        Console.Read();
    }
 }
}

因此,在我的理解中存在缺陷,上面给出了我在实施IEnumeratorIEnumerable后获得的相同结果。

5 个答案:

答案 0 :(得分:17)

  

然而,我可以在不使用任何一个

的情况下迭代自定义集合

当然可以在没有界面的情况下迭代你自己的集合; 如果你不能,那么你将如何实现界面?

作为代码实现者,您没有为 方便实现接口。您为了方便代码的使用者而实现它。界面意味着“关注客户:您可以枚举此集合的内容,而无需了解我如何实现它”。

这就是界面的目的:它提供了一种抽象,允许代码的消费者使用它而无需了解它的工作原理。

答案 1 :(得分:2)

main函数中,您使用person_list的两个方面来遍历人员列表,Length[]运算符以获取集合的成员某个位置。

但是,如果你有一些容器或自定义集合没有实现其中一个或两个呢?例如,逐行读取文件的类可能事先不知道集合的长度是多少,因此不能定义Length。从队列中读取消息的枚举器可能只能使用[4]来接收下一个,而不是前面的四个位置。在这两种情况下,您仍然可以正确地“迭代”整个集合。

IEnumeratorIEnumerable完全需要foreach工作所需的属性而不需要其他属性,这就是为什么函数可以将它们用作需求的原因,因为他们知道它们能够迭代他们通过的任何类型的集合。

答案 2 :(得分:1)

您当然可以在不实现IEnumerable接口的情况下迭代自定义集合,但迭代代码必须知道您的自定义集合。

如果您实现IEnumerable,则迭代所有元素的代码不需要知道您的person_list类。它使用实现IEnumerable某个类的实例,如果您将实际实例交换为稍后也实现IEnumerable的其他实例,它仍然有效。

答案 3 :(得分:1)

实际上,在C#中,不需要实现IEnumerableIEnumerator来自定义您自己的集合。如果您使用对您来说很好的传统方式迭代集合,但如果您使用 foreach 来迭代集合则会遇到麻烦。

另一个原因,如果你想暴露你的类以便VB.NET用户可以使用你应该考虑实现这两个接口。

请注意,IEnumerable在非泛型和通用集合中有所不同。非泛型属于System.Collection,另一个属于System.Collection.Generic命名空间

答案 4 :(得分:0)

有很多方法可以迭代自定义序列。一种方法是使用Iterator Design Pattern

Iterator Pattern用于统一遍历自定义序列(它可以是内存中的集合,生成的集合或其他内容)。在.NET世界中,这种模式以下列方式实现:我们有一个可迭代的对象,它实现了IEnumerable接口(这向你的班级的任何客户展示了你有能力遍历你的内容)。

我们有一个迭代器本身(实现IEnumerator接口的对象),您可以将其视为可迭代对象中当前位置的“指针”。因为你可能有内部循环(即一次在同一个对象上多次迭代),你必须从迭代器中拆分可迭代对象。

基本上有很多方法可以遍历特定的序列,但是Iterator Pattern让你能够“概括”这种方法,从实现中的调用者隐藏遍历算法的特定实现。