C# 我如何实现 IEnumerable<T>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11296810/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 17:17:35  来源:igfitidea点击:

How do I implement IEnumerable<T>

c#.netgenerics

提问by JMK

I know how to implement the non generic IEnumerable, like this:

我知道如何实现非通用 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();
        }
    }
}

However I also notice that IEnumerable has a generic version, IEnumerable<T>, but I can't figure out how to implement it.

但是我也注意到 IEnumerable 有一个通用版本IEnumerable<T>,但我不知道如何实现它。

If I add using System.Collections.Generic;to my using directives, and then change:

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

class MyObjects : IEnumerable

to:

到:

class MyObjects : IEnumerable<MyObject>

And then right click on IEnumerable<MyObject>and select Implement Interface => Implement Interface, Visual Studio helpfully adds the following block of code:

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

IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
    throw new NotImplementedException();
}

Returning the non generic IEnumerable object from the GetEnumerator();method doesn't work this time, so what do I put here? The CLI now ignores the non generic implementation and heads straight for the generic version when it tries to enumerate through my array during the foreach loop.

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

采纳答案by Monroe Thomas

If you choose to use a generic collection, such as List<MyObject>instead of ArrayList, you'll find that the List<MyObject>will provide both generic and non-generic enumerators that you can use.

如果您选择使用泛型集合,例如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();
    }
}

回答by Anders Abel

Why do you do it manually? yield returnautomates the entire process of handling iterators. (I also wrote about it on my blog, including a look at the compiler generated code).

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

If you really want to do it yourself, you have to return a generic enumerator too. You won't be able to use an ArrayListany more since that's non-generic. Change it to a List<MyObject>instead. That of course assumes that you only have objects of type MyObject(or derived types) in your collection.

如果你真的想自己做,你也必须返回一个通用的枚举器。您将无法再使用它,ArrayList因为它是非通用的。改为 a List<MyObject>。这当然假设您的集合中只有类型MyObject(或派生类型)的对象。

回答by ColWhi

make mylist into a List<MyObject>, is one option

将 mylist 变成一个List<MyObject>, 是一种选择

回答by user7116

You probably do not want an explicitimplementation of IEnumerable<T>(which is what you've shown).

您可能不想要(这就是您所展示的)的显式实现IEnumerable<T>

The usual pattern is to use IEnumerable<T>'s GetEnumeratorin the explicit implementation of IEnumerable:

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

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();
    }
}

回答by Amiram Korach

If you work with generics, use List instead of ArrayList. The List has exactly the GetEnumerator method you need.

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

List<MyObject> myList = new List<MyObject>();

回答by Shahar Shokrani

Note that the IEnumerable<T>allready implemented by the System.Collectionsso another approach is to derive your MyObjectsclass from System.Collectionsas a base class (documentation):

请注意,so 已经IEnumerable<T>实现的System.Collections另一种方法是将您的MyObjectsSystem.Collections作为基类(文档)派生:

System.Collections: Provides the base class for a generic collection.

System.Collections:提供泛型集合的基类。

We can later make our own implemenation to override the virtual System.Collectionsmethods to provide custom behavior (only for ClearItems, InsertItem, RemoveItem, and SetItemalong with Equals, GetHashCode, and ToStringfrom Object). Unlike the List<T>which is not designed to be easily extensible.

我们以后可以使我们自己实行重写虚拟System.Collections方法,以提供定制的行为(仅适用于ClearItemsInsertItemRemoveItem,和SetItem沿EqualsGetHashCode以及ToStringObject)。不像List<T>那些不是设计为易于扩展的。

Example:

例子:

public class FooCollection : System.Collections<Foo>
{
    //...
    protected override void InsertItem(int index, Foo newItem)
    {
        base.InsertItem(index, newItem);     
        Console.Write("An item was successfully inserted to MyCollection!");
    }
}

public static void Main()
{
    FooCollection fooCollection = new FooCollection();
    fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!
}

Please note that driving from collectionrecommended only in case when custom collection behavior is needed, which is rarely happens. see usage.

请注意,collection仅在需要自定义收集行为的情况下才推荐驱动,这种情况很少发生。见用法