it-swarm.com.de

Wie implementiere ich IEnumerable <T>

Ich weiß, wie man den nicht generischen IEnumerable wie folgt implementiert:

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

Allerdings stelle ich auch fest, dass IEnumerable eine generische Version hat, IEnumerable<T>, Aber ich kann nicht herausfinden, wie ich sie implementieren soll.

Wenn ich using System.Collections.Generic; Zu meinen using-Anweisungen hinzufüge und dann ändere:

class MyObjects : IEnumerable

zu:

class MyObjects : IEnumerable<MyObject>

Klicken Sie dann mit der rechten Maustaste auf IEnumerable<MyObject> Und wählen Sie Implement Interface => Implement Interface. Visual Studio fügt den folgenden Codeblock hilfreich hinzu:

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

Das Zurückgeben des nicht generischen IEnumerable-Objekts von der GetEnumerator(); -Methode funktioniert diesmal nicht. Was soll ich hier einfügen? Die CLI ignoriert jetzt die nicht generische Implementierung und sucht direkt nach der generischen Version, wenn sie während der foreach-Schleife versucht, mein Array zu durchlaufen.

114
JMK

Wenn Sie sich für die Verwendung einer allgemeinen Sammlung entscheiden, z. B. List<MyObject> anstelle von ArrayList finden Sie, dass die List<MyObject> bietet sowohl generische als auch nicht generische Enumeratoren, die Sie verwenden können.

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

Sie möchten wahrscheinlich keine explizite Implementierung von IEnumerable<T> (was du gezeigt hast).

Das übliche Muster ist IEnumerable<T> 's GetEnumerator in der expliziten Implementierung von 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();
    }
}
56
user7116

Warum machst du es manuell? yield return automatisiert den gesamten Prozess der Behandlung von Iteratoren. (Ich schrieb auch darüber in meinem Blog , einschließlich eines Blicks auf den vom Compiler generierten Code).

Wenn Sie es wirklich selbst tun möchten, müssen Sie auch einen generischen Enumerator zurückgeben. Sie können kein ArrayList mehr verwenden, da dies nicht generisch ist. Ändern Sie es in ein List<MyObject> stattdessen. Das setzt natürlich voraus, dass Sie nur Objekte vom Typ MyObject (oder abgeleitete Typen) in Ihrer Sammlung haben.

24
Anders Abel

Wenn Sie mit Generika arbeiten, verwenden Sie List anstelle von ArrayList. Die Liste enthält genau die GetEnumerator-Methode, die Sie benötigen.

List<MyObject> myList = new List<MyObject>();
4
Amiram Korach

mache mylist zu einem List<MyObject>, ist eine Option

0
ColWhi