147

私は次のように非ジェネリック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、VisualStudioは次のコードブロックを追加します。

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

今回は、メソッドから非ジェネリックIEnumerableオブジェクトを返すことGetEnumerator();はできません。そこで、ここに何を入れますか?CLIは、非ジェネリック実装を無視し、foreachループ中に配列を列挙しようとすると、ジェネリックバージョンに直接向かいます。

4

6 に答える 6

171

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();
    }
}
于 2012-07-02T15:45:53.823 に答える
82

おそらく明示的な実装は必要ありません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();
    }
}
于 2012-07-02T15:41:23.267 に答える
25

なぜ手動で行うのですか?yield returnイテレータを処理するプロセス全体を自動化します。(コンパイラによって生成されたコードも含めて、ブログにも書いています)。

本当に自分でやりたい場合は、ジェネリック列挙子も返す必要があります。ArrayListは非ジェネリックであるため、これ以上使用することはできません。代わりに a に変更しList<MyObject>ます。MyObjectもちろん、コレクションにある型 (または派生型)のオブジェクトのみを持っていることを前提としています。

于 2012-07-02T15:37:40.223 に答える
5

ジェネリックを使用する場合は、ArrayList の代わりに List を使用します。List には、必要な GetEnumerator メソッドが正確に含まれています。

List<MyObject> myList = new List<MyObject>();
于 2012-07-02T15:42:15.283 に答える
0

mylist を にします。これList<MyObject>は 1 つのオプションです

于 2012-07-02T15:40:12.627 に答える