2013-01-16 14 views
5

Mögliche Duplizieren:
Implementing C# IEnumerable<T> for a LinkedList classUmsetzung IEnumerable zu meinem Objekt

Ich kann das Netz für einige Stunden jetzt noch nicht verstehen, wie IEnumerable/IEnumerator funktioniert und wie es nach der Suche zu implementieren .

Ich habe eine einfache LinkedList von Grund auf neu gebaut, aber jetzt möchte ich IEnumerable für sie implementieren, damit ich es foreach kann. Wie mache ich das?

class Program 
{ 
    LL myList = new LL(); 

    static void Main() 
    { 
     var gogo = new Program(); 
    } 
    public Program() 
    { 

     myList.Add("test"); 
     myList.Add("test1"); 

     foreach (var item in myList) //This doesn't work because I havn't implemented Ienumerable 
      Console.WriteLine(item); 

     Console.Read(); 
    } 
} 


class LL 
{ 

    private LLNode first; 

    public void Add(string s) 
    { 
     if (this.first == null) 
      this.first = new LLNode() { Value = s }; 
     else 
     { 
      var node = this.first; 
      while (node.Next != null) 
       node = node.Next; 

      node.Next = new LLNode() { Value = s }; 
     } 
    } 


class LLNode 
{ 
    public string Value { get; set; } 
    public LLNode Next { get; set; } 
} 
+4

sind Sie sicher, Sie haben es versucht? – Nahum

+1

[Hier] (http://codebetter.com/davidhayden/2005/03/08/implementing-ienumerable-and-ienumerator-on-your-custom-objects/) ist * kein gutes Tutorial zur Implementierung von 'IEnumerable' on eine benutzerdefinierte Klasse [Hier] (http://www.codeproject.com/Articles/474678/A-Beginners-Tutorial-on-Implementing-IEnumerable-I) ist eine bessere. – NominSim

+0

Beachten Sie, dass Sie * IEnumerable' technisch nicht implementieren müssen, um Ihre Klasse mit einer 'foreach'-Schleife zu verwenden ... – sloth

Antwort

3

Was müssen Sie tun, ist:

(1) Stellen Sie Ihre Klasse > IEnumerable < T implementieren, wobei T der Typ der aufgezählten Artikel. (In Ihrem Fall sieht es so aus, als wäre es LLNode).

(2) Schreiben Sie eine öffentliche IEnumerator <T> GetEnumerator. Implementieren Sie es mit dem Schlüsselwort "yield".

(3) Fügen Sie eine IEnumerator IEnumerable.GetEnumerator() -Methode hinzu und geben Sie GetEnumerator() zurück.

Der folgende Code sollte dies verdeutlichen. Wo ich <int> habe, sollten Sie setzen <LLNode>, vorausgesetzt, dass der richtige Typ ist.

Ich hätte Ihren Code geändert, um es richtig zu machen, aber der Code, den Sie gepostet haben, wird nicht kompiliert.

[EDIT]

Jetzt haben Sie Ihren Code aktualisiert, kann ich sehen, dass Sie die Werte auflisten möchten. Hier ist der vollständige Code:

using System; 
using System.Collections; 
using System.Collections.Generic; 

namespace Demo 
{ 
    internal class Program 
    { 
     private LL myList = new LL(); 

     private static void Main() 
     { 
      var gogo = new Program(); 
     } 

     public Program() 
     { 
      myList.Add("test"); 
      myList.Add("test1"); 

      foreach (var item in myList) // This now works. 
       Console.WriteLine(item); 

      Console.Read(); 
     } 
    } 


    internal class LL: IEnumerable<string> 
    { 
     private LLNode first; 

     public void Add(string s) 
     { 
      if (this.first == null) 
       this.first = new LLNode 
       { 
        Value = s 
       }; 
      else 
      { 
       var node = this.first; 
       while (node.Next != null) 
        node = node.Next; 

       node.Next = new LLNode 
       { 
        Value = s 
       }; 
      } 
     } 

     public IEnumerator<string> GetEnumerator() 
     { 
      for (var node = first; node != null; node = node.Next) 
      { 
       yield return node.Value; 
      } 
     } 

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

     private class LLNode 
     { 
      public string Value { get; set; } 
      public LLNode Next { get; set; } 
     } 
    } 
} 
+0

Versuchen Sie es jetzt zu kompilieren, ohne die foreach-Schleife und WriteLite. –

+0

Danke, dass es jetzt funktioniert. Jetzt werde ich es studieren. –

6

Es ist wirklich nicht so schwer. Um IEnumerable zu implementieren, müssen Sie nur die Methode GetEnumerator implementieren. Dazu müssen Sie eine andere Klasse erstellen, die IEnumerator implementiert. Die Implementierung von IEnumerator ist ziemlich einfach. Im Allgemeinen übergeben Sie einen Verweis auf Ihre Sammlung, wenn Sie den Enumerator (in GetEnumerator) erstellen und der Enumerator verfolgt, welches Element das aktuelle Element ist. Dann liefert es MoveNext, die nur die Current zum nächsten Element ändert (und false zurückgibt, wenn es am Ende der Liste ist) und Reset, die Current zurück zu vor der erste Knoten setzt.

So in sehr breit, nicht getesteten Code Begriffe, müssen Sie so etwas wie:

public class MyLinkedListEnumerator : IEnumerator 
{ 
    private LL myList; 
    private LLNode current; 

    public object Current 
    { 
     get { return current; } 
    } 

    public MyLinkedListEnumerator(LL myList) 
    { 
     this.myList = myList; 
    } 

    public bool MoveNext() 
    { 
     if (current == null) { 
      current = myList.first; 
     } 
     else { 
      current = current.Next; 
     } 
     return current != null; 
    } 

    public void Reset() 
    { 
     current = null; 
    } 
} 
+0

Nur um darauf hinzuweisen, C# hilft Ihnen dabei sehr, wenn Sie die 'GetEnumerator()' Methode selbst mit 'yield' Anweisungen erstellen. – NominSim

+0

Ich bekomme den Fehler Inkonsistente Zugänglichkeit: Parametertyp 'xx.LL 'ist weniger zugänglich als Methode' xx.MyLinkedListEnumerator.MyLinkedListEnumerator (xx.LL) '\t C: \\ xx \ Program.cs Fehler –

+0

@Ben: Das liegt wahrscheinlich daran, dass Ihre 'LL'-Klasse privat ist. Markiere es öffentlich. –