2013-01-16 17 views
5

Eventuali duplicati:
Implementing C# IEnumerable<T> for a LinkedList classImplementazione IEnumerable al mio oggetto

Dopo la ricerca sul web per qualche ora ora non riesco ancora a capire come IEnumerable/IEnumerator opere e come implementarlo .

Ho costruito un semplice LinkedList da zero, ma ora voglio implementare IEnumerable così da poterlo foreach. Come lo faccio?

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

sei sicuro di aver provato? – Nahum

+1

[Qui] (http://codebetter.com/davidhayden/2005/03/08/implementing-ienumerable-and-ienumerator-on-your-custom-objects/) non * è un buon tutorial sull'implementazione di 'IEnumerable' su una lezione personalizzata [Qui] (http://www.codeproject.com/Articles/474678/A-Beginners-Tutorial-on-Implementing-Inumerable-I) è migliore. – NominSim

+0

Nota che, tecnicamente, non * non * è necessario * per implementare 'IEnumerable' per usare la tua classe con un ciclo' foreach' ... – sloth

risposta

3

Quello che dovete fare è:

(1) Fai la tua classe di implementare IEnumerable <T> dove T è il tipo degli elementi elencati. (Nel tuo caso, sembra che sarebbe LLNode).

(2) Scrivere un IEnumeratore pubblico <T> GetEnumerator. Implementalo usando la parola chiave "rendimento".

(3) Aggiungere un metodo IEnumerator IEnumerable.GetEnumerator() e restituire semplicemente GetEnumerator().

Il seguente codice deve essere chiaro. Dove ho <int>, dovresti inserire <LLNode>, supponendo che sia il tipo corretto.

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

namespace Demo 
{ 
    internal class Program 
    { 
     private static void Main() 
     { 
      var test = new MyDemo(); 

      foreach (int item in test) 
      { 
       Console.WriteLine(item); 
      } 
     } 
    } 

    public class MyDemo: IEnumerable<int> 
    { 
     public IEnumerator<int> GetEnumerator() 
     { 
      // Your implementation of this method will iterate over your nodes 
      // and use "yield return" to return each one in turn. 

      for (int i = 10; i <= 20; ++i) 
      { 
       yield return i; 
      } 
     } 

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

Avrei modificato il codice per farlo correttamente, ma il codice che hai postato non verrà compilato.

[EDIT]

Ora che hai aggiornato il tuo codice, vedo che si desidera enumerare i valori. Ecco il codice completato:

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

Prova a compilarlo ora, senza il ciclo foreach e WriteLite. –

+0

Grazie funziona ora. Adesso lo studierò. –

6

Non è davvero così difficile. Per implementare IEnumerable è sufficiente implementare il metodo GetEnumerator.

Per fare ciò è necessario creare un'altra classe che implementa IEnumerator. L'implementazione di IEnumerator è piuttosto semplice. Generalmente si passa un riferimento alla raccolta quando si crea l'enumeratore (in GetEnumerator) e l'enumeratore tiene traccia di quale elemento è l'elemento corrente. Quindi fornirà MoveNext che modifica semplicemente lo Current all'elemento successivo (e restituisce falso se è alla fine dell'elenco) e Reset che imposta lo prima del prima del primo nodo.

Quindi, in termini molto ampi codice non testato,, avete bisogno di qualcosa di simile:

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

Solo per sottolineare, C# ti aiuta molto con questo se crei tu stesso il metodo 'GetEnumerator()' con le istruzioni 'yield' ecc. – NominSim

+0

Ricevo l'errore: Accessibilità incoerente: tipo di parametro 'xx.LL 'è meno accessibile del metodo' xx.MyLinkedListEnumerator.MyLinkedListEnumerator (xx.LL) '\t C: \\ xx \ Program.cs error –

+0

@Ben: Probabilmente è perché la classe 'LL' è privata. Segnalo pubblico. –