我如何实现IEnumerable <T>

JMK*_*JMK 118 .net c# generics

我知道如何实现非通用IEnumerable,如下所示:

using System;
using System.Collections;

namespace ConsoleApplication33
{
    class Program
    {
        static void Main(string[] args)
        {
            MyObjects myObjects = new MyObjects();
            myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 };
            myObjects[1] = new MyObject() { Foo = "World", Bar = 2 };

            foreach (MyObject x in myObjects)
            {
                Console.WriteLine(x.Foo);
                Console.WriteLine(x.Bar);
            }

            Console.ReadLine();
        }
    }

    class MyObject
    {
        public string Foo { get; set; }
        public int Bar { get; set; }
    }

    class MyObjects : IEnumerable
    {
        ArrayList mylist = new ArrayList();

        public MyObject this[int index]
        {
            get { return (MyObject)mylist[index]; }
            set { mylist.Insert(index, value); }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return mylist.GetEnumerator();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我也注意到IEnumerable有一个通用版本IEnumerable<T>,但我无法弄清楚如何实现它.

如果我添加using System.Collections.Generic;到我的using指令,然后更改:

class MyObjects : IEnumerable
Run Code Online (Sandbox Code Playgroud)

至:

class MyObjects : IEnumerable<MyObject>
Run Code Online (Sandbox Code Playgroud)

然后右键单击IEnumerable<MyObject>并选择Implement Interface => Implement Interface,Visual Studio有助于添加以下代码块:

IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

从这个GetEnumerator();方法返回非通用IEnumerable对象这次不起作用,那么我在这里放什么呢?CLI现在忽略了非泛型实现,并在foreach循环期间尝试枚举我的数组时直接针对泛型版本.

Mon*_*mas 141

如果您选择使用泛型集合(例如List<MyObject>代替)ArrayList,您将发现List<MyObject>它将提供您可以使用的泛型和非泛型枚举器.

using System.Collections;

class MyObjects : IEnumerable<MyObject>
{
    List<MyObject> mylist = new List<MyObject>();

    public MyObject this[int index]  
    {  
        get { return mylist[index]; }  
        set { mylist.Insert(index, value); }  
    } 

    public IEnumerator<MyObject> GetEnumerator()
    {
        return mylist.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @TannerSwett 没有区别。 (2认同)

use*_*116 62

您可能不希望显式实现IEnumerable<T>(这是您所显示的).

通常的模式是IEnumerable<T>在IEnumerable的显式实现中使用'GetEnumerator:

class FooCollection : IEnumerable<Foo>, IEnumerable
{
    SomeCollection<Foo> foos;

    // Explicit for IEnumerable because weakly typed collections are Bad
    System.Collections.IEnumerator IEnumerable.GetEnumerator()
    {
        // uses the strongly typed IEnumerable<T> implementation
        return this.GetEnumerator();
    }

    // Normal implementation for IEnumerable<T>
    IEnumerator<Foo> GetEnumerator()
    {
        foreach (Foo foo in this.foos)
        {
            yield return foo;
            //nb: if SomeCollection is not strongly-typed use a cast:
            // yield return (Foo)foo;
            // Or better yet, switch to an internal collection which is
            // strongly-typed. Such as List<T> or T[], your choice.
        }

        // or, as pointed out: return this.foos.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好点子.但实现`IEnumerable`是多余的(`IEnumerable <T>`已经从它继承). (8认同)
  • 如果SomeCollection &lt;T&gt;尚未实现IEnumerable &lt;T&gt;,或者在枚举序列中返回每个元素之前需要对其进行转换或其他处理,则这是一个很好的解决方案。如果这两个条件都不成立,则仅返回this.foos.GetEnumerator();可能会更高效。 (2认同)

And*_*bel 24

你为什么要手动做?yield return自动化处理迭代器的整个过程.(我也在我的博客上写过它,包括看一下编译器生成的代码).

如果你真的想自己做,你也必须返回一个通用的枚举器.你不能再使用了,ArrayList因为那是非泛型的.将其更改为一个List<MyObject>来代替.当然,假设您的集合中只有类型MyObject(或派生类型)的对象.

  • 除非OP将在枚举器中进行一些处理,否则使用yield return只会增加另一个状态机的开销.OP应该只返回由底层泛型集合提供的枚举器. (5认同)
  • +1,应该注意的是,首选模式是实现通用接口并明确实现非通用接口.产量回报是通用接口的最自然的解决方案. (2认同)

Ami*_*ach 5

如果您使用泛型,请使用 List 而不是 ArrayList。List 正是您需要的 GetEnumerator 方法。

List<MyObject> myList = new List<MyObject>();
Run Code Online (Sandbox Code Playgroud)