2012-01-06 8 views
26

Sto provando a scrivere la mia (semplice) implementazione di List. Questo è quello che ho fatto finora:Problemi di implementazione di IEnumerable <T>

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace provaIEnum 
{ 
    class MyList<T> : IEnumerable<T> 
    { 
     private T[] _array; 
     public int Count { get; private set; } 

     public MyList() { /* ... */ } 
     public void Add(T element) { /* ... */ } 

     // ... 

     public IEnumerator<T> GetEnumerator() 
     { 
      for (int i = 0; i < Count; i++) 
       yield return _array[i]; 
     } 
    } 

Ricevo un errore circa GetEnumerator però:

'provaIEnum.Lista' non implementa il membro di interfaccia 'System.Collections.IEnumerable.GetEnumerator()'. 'provaIEnum.Lista.GetEnumerator()' non può implementare 'System.Collections.IEnumerable.GetEnumerator()' perché non ha il tipo restituito corrispondente a 'System.Collections.IEnumerator'.

Non sono sicuro di aver capito cosa sta cercando di dirmi VS e non ho idea di come risolverlo.

Grazie per il vostro tempo

+0

Si noti che non si dovrebbe scrivere il proprio enumeratore in questo modo poiché attualmente è possibile modificare l'array interno in un 'foreach' (chiamare' Add' in foreach non causerà un'eccezione). [Vedi] (http://stackoverflow.com/questions/24142614/when-should-i-separately-implement-ienumeratort) – nawfal

+0

@nawfal buon punto, i bug ci guardano sempre;) – BlackBear

risposta

41

Dal IEnumerable<T> attrezzi IEnumerable è necessario implementare questa interfaccia così nella classe che ha la versione non generica del metodo GetEnumerator. Per evitare conflitti è possibile implementare in modo esplicito:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    // call the generic version of the method 
    return this.GetEnumerator(); 
} 

public IEnumerator<T> GetEnumerator() 
{ 
    for (int i = 0; i < Count; i++) 
     yield return _array[i]; 
} 
+1

Grazie, non sapevo IEnumerable implementa IEnumerable (anche se sembra ovvio: P) – BlackBear

+5

Dato che non hai qualificato esplicitamente 'IEnumerator' e' IEnumerable.GetEnumerator' con 'System.Collections', questo non funzionerà se non si usa' System.Collections'. , dicendo (piuttosto inutilmente) che 'IEnumerator' ha bisogno di un argomento generico! – PJTraill

10

Avrete bisogno di implementare il metodo GetEnumerator non generico così:

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

Poiché l'interfaccia IEnumerable<T> estende IEnumerable, è necessario implementare la metodi dichiarati su entrambi.

+0

Implementazioni esplicite dell'interfaccia non devono avere un modificatore di accesso – Nuffin

36

Leggere più attentamente il messaggio di errore; ti sta dicendo esattamente cosa devi fare. Non hai implementato System.Collections.IEnumerable.GetEnumerator.

Quando si implementa il genericaIEnumerable<T> è necessario implementare anche GetEnumerator System.Collections.IEnumerable s'.

Il metodo standard per farlo è:

public IEnumerator<T> GetEnumerator() { whatever } 
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
{ 
    return this.GetEnumerator(); 
} 
+0

+1 per la "modalità standard", continua ad imparare ogni giorno :) – BlackBear

4

Aggiungere il seguente metodo:

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

Ci sono due overload di GetEnumerator() che è necessario implementare. Uno viene da IEnumerable<T> e restituisce IEnumerator<T>. L'altro proviene da IEnumerable e restituisce IEnumerator. L'override dovrebbe essere così:

IEnumerator IEnumerable.GetEnumerator()

Questo perché IEnumerable<T> implementa IEnumerable.

1

Poiché la classe, MyList<T> eredita IEnumerable<out T> che a sua volta eredita il non generico IEnumerable, ci sono due metodi che è necessario implementare:

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

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      throw new NotImplementedException(); 
     } 

Un modo semplice per farlo è quando si dichiara la classe:

class MyList<T> : IEnumerable<T> 

clic destro il testo IEnumerable<T> e selezionare implementare l'interfaccia> Implementa interfaccia esplicitamente dal menu contestuale.

0

Ho avuto un problema simile, anche se ho implementato anche IEnumerable e IEnumerable. Stavo usando il tipo personalizzato (Person class) rispetto al tipo generico T. Per me il motivo era, lo spazio dei nomi non era incluso nella parte superiore del file.

using System.Collections; 

Dopo aver aggiunto lo spazio dei nomi, per me andava bene.

Problemi correlati