簡體   English   中英

我如何實現IEnumerable <T>

[英]How do I implement IEnumerable<T>

我知道如何實現非通用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 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對象GetEnumerator(); 這個方法不起作用,所以我放在這里呢? CLI現在忽略了非泛型實現,並且在foreach循環期間嘗試枚舉我的數組時,直接針對泛型版本。

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

您可能不希望顯式實現IEnumerable<T> (這是您所展示的)。

通常的模式是使用IEnumerable<T>GetEnumerator在顯式執行IEnumerable

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

你為什么要手動做? yield return自動完成處理迭代器的整個過程。 (我也在我的博客上寫過它,包括看一下編譯器生成的代碼)。

如果你真的想自己做,你也必須返回一個通用的枚舉器。 您將無法再使用ArrayList因為它不是通用的。 將其更改為List<MyObject> 當然,假設您的集合中只有MyObject (或派生類型)類型的對象。

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

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

將mylist設為List<MyObject> ,是一個選項

請注意, IEnumerable<T>System.Collections實現,因此另一種方法是從System.Collections派生MyObjects類作為基類( 文檔 ):

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

我們以后可以自己實現覆蓋虛擬System.Collections方法來提供自定義行為(僅適用於ClearItemsInsertItemRemoveItemSetItem以及來自Object EqualsGetHashCodeToString )。 List<T>不同, 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推薦,這種情況很少發生。 看看用法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM