.net 如何实现IEnumerable< T>

a8jjtwal  于 2023-05-23  发布在  .NET
关注(0)|答案(7)|浏览(182)

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

然而,我也注意到IEnumerable有一个泛型版本IEnumerable<T>,但我不知道如何实现它。
如果我将using System.Collections.Generic;添加到using指令中,然后更改:

class MyObjects : IEnumerable

致:

class MyObjects : IEnumerable<MyObject>

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

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

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

mw3dktmi

mw3dktmi1#

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

bq3bfh9z2#

您可能不需要IEnumerable<T>的 * 显式 * 实现(这就是您所展示的)。
通常的模式是在IEnumerable的显式实现中使用IEnumerable<T>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();
    }
}
bz4sfanl

bz4sfanl3#

为什么要手动操作?yield return自动化处理迭代器的整个过程。(我还写了关于它的on my blog,包括查看编译器生成的代码)。
如果你真的想自己做,你也必须返回一个泛型枚举数。您将不能再使用ArrayList,因为它是非泛型的。将其改为List<MyObject>。当然,这是假设集合中只有MyObject类型(或派生类型)的对象。

2w2cym1i

2w2cym1i4#

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

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

iqjalb3h5#

将mylist转换为List<MyObject>是一种选择

5n0oy7gb

5n0oy7gb6#

请注意,IEnumerable<T>已经由System.Collections实现,所以另一种方法是从System.Collections派生MyObjects类作为基类(documentation):
System.Collections:为泛型集合提供基类。
我们可以稍后进行自己的实现来覆盖虚拟System.Collections方法以提供自定义行为(仅适用于ClearItemsInsertItemRemoveItemSetItem沿着EqualsGetHashCodeToString)。不像List<T>,它的设计不容易扩展。
示例:

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!
}

请注意,仅在需要自定义收集行为的情况下,才建议从collection驱动,这种情况很少发生。参见usage

eni9jsuy

eni9jsuy7#

.....不要忘记使用,如果你被阻止

IEnumerator IEnumerable.GetEnumerator()
    {
        // uses the strongly typed IEnumerable<T> implementation
        return GetEnumerator();
    }

添加此内容:

using System.Collections;

此外:

: IEnumerable<string>

这是一个很好的例子,因为它包含了IEnumerable:

public interface IEnumerable<out T> : IEnumerable

...还要注意enumrAble中的A和enumratOr中的o之间的语法笑话,这两个都在这个模式中使用!漂亮的危险线:

IEnumerator IEnumerable.GetEnumerator()

相关问题