2008-09-24 4 views

Antwort

7

Methode 1: Verwenden Sie weiterhin die Kapselung und leiten Sie Aufrufe an die List-Implementierung weiter.

class SomeObject 
{ 
} 

class MyEnum : IEnumerable<SomeObject> 
{ 
    private List<SomeObject> _myList = new List<SomeObject>(); 

    public void Add(SomeObject o) 
    { 
     _myList.Add(o); 
    } 

    public IEnumerator<SomeObject> GetEnumerator() 
    { 
     return _myList.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyEnum a = new MyEnum(); 
     a.Add(new SomeObject()); 

     foreach (SomeObject o in a) 
     { 
      Console.WriteLine(o.GetType().ToString()); 
     } 

     Console.ReadLine(); 
    } 
} 

Methode 2: vererben Liste Implementierung Sie dieses Verhalten kostenlos.

class SomeObject 
{ 
} 

class MyEnum : List<SomeObject> 
{ 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyEnum a = new MyEnum(); 
     a.Add(new SomeObject()); 

     foreach (SomeObject o in a) 
     { 
      Console.WriteLine(o.GetType().ToString()); 
     } 

     Console.ReadLine(); 
    } 
} 

Methode 1 ermöglicht eine bessere Sandbox, da es keine Methode, die ohne MyEnum Wissen in Liste aufgerufen werden. Für den geringsten Aufwand wird Methode 2 bevorzugt.

-1

Nicht, wenn Sie nicht von der Liste < T> abgeleitet sind.

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{} 
+0

Ok, dies funktionieren wird, aber ich möchte sicher sein, dass der anrufende Code ist nicht in der Lage Art-casting den Enumerator erneut auflisten und Objekte hinzufügen oder daraus entfernen. – Willem

1

Sie können dies tun:

public class MyEnum : IEnumerator { 
    private List<SomeObject> _myList = new List<SomeObject>(); 
    public IEnumerator GetEnumerator() { return this._myList.GetEnumerator(); } 
} 

Der Grund ist einfach. Ihre Klasse kann mehrere Felder enthalten, die Sammlungen sind, so dass der Compiler/die Umgebung nicht wissen kann, welches Feld für die Implementierung von "IEnumerator" verwendet werden soll.

EIDT: ich mit @pb einverstanden - Sie IEnumerator <Someobject> Schnittstelle implementiert sollte.

+0

Die zu implementierende Schnittstelle ist IEnumerable nicht IEnumerator. –

0

Wenn Sie Rückkehr in einer Weise, eine Sammlung wollen, wo der Anrufer nicht in der Lage ist, die Sammlung zu ändern, könnten Sie die Liste in eine Readonlycollection < wickeln wollen> und Rückkehr IEnumerable <> der Readonlycollection <>.

Auf diese Weise können Sie sicher sein, dass Ihre Sammlung nicht geändert wird.

1

Abgesehen von der Verwendung der Methode von pb ist dies aus einem "einfachen" Grund nicht möglich: Die Schnittstellenmethode muss einen this Zeiger als erstes Argument übergeben bekommen. Wenn Sie GetEnumerator auf Ihrem Objekt aufrufen, wird dieser Zeiger Ihr Objekt sein. Damit der Aufruf an der verschachtelten Liste funktioniert, müsste der Zeiger jedoch ein Verweis auf diese Liste und nicht auf Ihre Klasse sein.

Daher müssen Sie die Methode explizit an das andere Objekt delegieren.

(Und übrigens, die Beratung in der anderen Antwort war richtig: Verwenden Sie IEnumerator<T>, nichtIEnumerable!)

-1

Vielen Dank für Ihre Eingabe und Erklärungen. Schließlich habe ich einige Ihrer Antworten kombiniert, um die folgenden:

class MyEnum : IEnumerable<SomeObject> 
{ 
    private List<SomeObject> _myList = new List<SomeObject>(); 
    public IEnumerator<SomeObject> GetEnumerator() 
    { 
     // Create a read-only copy of the list. 
     ReadOnlyCollection<CustomDevice> items = new ReadOnlyCollection<CustomDevice>(_myList); 
     return items.GetEnumerator(); 
    } 
} 

Diese Lösung ist der aufrufende Code nicht in der Lage ist, um sicherzustellen, um die Liste der Modifizierung und jeder Enumerator ist unabhängig von den anderen in jeder Hinsicht (zB mit Sortierung) . Danke nochmal.

+0

Sie können die 'ReadOnlyCollection' passieren, weil 'IEnumerable's sowieso unveränderlich sind! Der Benutzer muss den Originaltyp der Liste aktualisieren und erraten, um ihn zu ändern. Kopieren der Liste ist IMHO keine sehr gute Idee. –

-1

Beachten Sie, dass dank duck-typing Sie foreach auf ein beliebiges Objekt verwenden können, die eine GetEnumerator Methode hat - der Objekttyp nicht wirklich IEnumerable implementieren muss.

Also, wenn Sie dies tun:

class SomeObject 
{ 
} 

class MyEnum 
{ 
    private List<SomeObject> _myList = new List<SomeObject>(); 

    public IEnumerator<SomeObject> GetEnumerator() 
    { 
     return _myList.GetEnumerator(); 
    } 
} 

Dann funktioniert das ganz gut:

MyEnum objects = new MyEnum(); 
// ... add some objects 
foreach (SomeObject obj in objects) 
{ 
    Console.WriteLine(obj.ToString()); 
} 
+0

Ich weiß, dass dies keine allgemeine Antwort auf die ursprüngliche Frage ist, aber es ist relevant für den spezifischen Anwendungsfall, der in der Frage bereitgestellt wird. – yoyo

+0

Wenn Sie feststellen, dass Sie die Frage nicht beantworten, * schreiben Sie keine Antwort auf die Frage *. Antworten sind für die Beantwortung der Frage, nicht für das Posten zufälliger trivialer Tatsachen, die Sie interessant finden. Dies hilft dir in dieser Situation nicht wirklich; Es gibt keinen Grund für Sie, die Schnittstelle in dieser Situation nicht wirklich zu implementieren. – Servy

+0

Die Frage war, wie die Implementierung einer Schnittstelle delegiert werden sollte, um das Schreiben von Codebausteinen zu vermeiden. Meine Antwort ist eine mögliche Antwort auf den häufigen Fall, dass die Umsetzung von IEnumerable delegiert wird, was übrigens auch das Beispiel des OP ist. Ich überlegte, ob ich es kommentieren oder beantworten sollte, und ich beschloss, eine Antwort zu geben. Es * ist * eine Antwort auf eine bestimmte Form der Frage. – yoyo