2012-01-06 21 views
26

Estoy intentando escribir mi propia implementación (simple) de List. Esto es lo que he hecho hasta ahora:Problemas para implementar 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]; 
     } 
    } 

Recibo un error sobre GetEnumerator sin embargo:

'provaIEnum.Lista' no implementa miembro de interfaz 'System.Collections.IEnumerable.GetEnumerator() '. 'provaIEnum.Lista.GetEnumerator()' no puede implementar 'System.Collections.IEnumerable.GetEnumerator()' porque no tiene tiene el tipo de retorno coincidente de 'System.Collections.IEnumerator'.

No estoy seguro si entiendo lo que VS intenta decirme y no tengo ni idea de cómo solucionarlo.

Gracias por su tiempo

+0

Tenga en cuenta que no debe escribir su enumerador de esa manera ya que actualmente puede modificar su matriz interna en un 'foreach' (llamando' Add' en foreach no causará una excepción). [Ver] (http://stackoverflow.com/questions/24142614/when-should-i-separately-implement-ienumeratort) – nawfal

+0

@nawfal buen punto, los errores siempre nos están mirando;) – BlackBear

Respuesta

41

Desde IEnumerable<T> implementos IEnumerable que necesita para implementar esta interfaz, así como en su clase que tiene la versión no genérica del método GetEnumerator. Para evitar conflictos podría implementar explícitamente:

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

Gracias, no sabía IEnumerable implementa IEnumerable (aunque suena obvio: P) – BlackBear

+5

Dado que no ha calificado explícitamente 'IEnumerator' y' IEnumerable.GetEnumerator' con 'System.Collections', esto fallará si no tiene' using System.Collections' , diciendo (bastante inútil) que 'IEnumerator' necesita un argumento genérico! – PJTraill

10

Tendrá que aplicar el método GetEnumerator no genérico, así:

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

Desde la interfaz IEnumerable<T> extiende IEnumerable, usted tiene que poner en práctica el métodos declarados en ambos.

+0

Las implementaciones de interfaces explícitas no deben tener un modificador de acceso – Nuffin

36

Lea el mensaje de error con más cuidado; te está diciendo exactamente lo que debes hacer. No implementó System.Collections.IEnumerable.GetEnumerator.

Cuando se implementa la genéricaIEnumerable<T> hay que aplicar también GetEnumerator System.Collections.IEnumerable 's.

La forma habitual de hacerlo es:

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

+1 para la 'forma estándar', sigue aprendiendo todos los días :) – BlackBear

4

añade el siguiente método:

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

Hay dos sobrecargas de GetEnumerator() que debe implementar. Uno viene de IEnumerable<T> y devuelve IEnumerator<T>. El otro viene de IEnumerable y devuelve IEnumerator. La anulación debe tener este aspecto:

IEnumerator IEnumerable.GetEnumerator()

Esto se debe a IEnumerable<T> implementa IEnumerable.

1

Dado que la clase, MyList<T> hereda IEnumerable<out T> que a su vez hereda el no genérico IEnumerable, tiene dos métodos es necesario implementar:

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

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

Una manera fácil de hacer esto es cuando se declara su clase:

class MyList<T> : IEnumerable<T> 

Haga clic derecho en el texto y seleccione IEnumerable<T>implementar la interfaz> Implementar interfaz explicitamente en el menú contextual.

0

Tengo un problema similar, aunque también implementé IEnumerable e IEnumerable. Estaba usando un tipo personalizado (clase Person) que el tipo genérico T. Para mí, la razón era que el espacio de nombres no estaba incluido en la parte superior del archivo.

using System.Collections; 

Después de agregar el espacio de nombres estaba bien para mí.

Cuestiones relacionadas