2010-03-12 12 views
16

Dada una clase base con la siguiente interfaz:bloques Iterator y la herencia

public class Base 
{ 
    public virtual IEnumerable<string> GetListOfStuff() 
    { 
     yield return "First"; 
     yield return "Second"; 
     yield return "Third"; 
    } 
} 

Quiero hacer una clase derivada que reemplaza el método, y añade su propio material, así:

public class Derived : Base 
{ 
    public override IEnumerable<string> GetListOfStuff() 
    { 
     foreach (string s in base.GetListOfStuff()) 
     { 
      yield return s; 
     } 

     yield return "Fourth"; 
     yield return "Fifth"; 
    } 
} 

Sin embargo, recibí una advertencia de que "no se puede verificar el acceso a un miembro a través de una palabra clave básica de un iterador".

¿Cuál es la solución aceptada para este problema, entonces?

+6

Tenga en cuenta que esto está resuelto en C# 4 (y ... en C# 3 SP 1? Tal vez? No recuerdo si obtuvimos esa solución o no. Lo intentamos). El compilador ahora genera el ayudante para tú. –

+0

Recibí la advertencia en VS2008 SP1. –

Respuesta

11

¿Qué tal:

public class Derived : Base 
{ 
    public override IEnumerable<string> GetListOfStuff() 
    { 
     return base.GetListOfStuff().Concat(GetMoreStuff());   
    } 
    private IEnumerable<string> GetMoreStuff() 
    { 
     yield return "Fourth"; 
     yield return "Fifth"; 
    } 
} 
+0

En lugar de una función de ayuda para las cosas básicas, una función de ayuda para las cosas en esta clase. ¡Buena idea! –

3

Se debe a que el iterador se convirtió en una clase privada, y el acceso a los métodos de superclase de una clase interna no es verificable (ya que tiene que forzar el puntero 'this' a algo distinto que sí mismo).

intente crear un nuevo método privado en Derived:

private IEnumerable<string> GetBaseListOfStuff() 
{   
    return base.GetListOfStuff(); 
} 

y que en lugar de llamar a base.GetListOfStuff()

3

Parece que una solución era seguir simplemente lo que el "manual" dice: hacer una función auxiliar.

Así que por ahora he resuelto de esta manera:

public class Derived : Base 
{ 
    private IEnumerable<string> GetBaseStuff() 
    { 
     return base.GetListOfStuff(); 
    } 

    public override IEnumerable<string> GetListOfStuff() 
    { 
     foreach (string s in GetBaseStuff()) 
     { 
      yield return s; 
     } 

     yield return "Fourth"; 
     yield return "Fifth"; 
    } 
} 

pero tengo curiosidad acerca de otras soluciones, así, si los hubiere.

+0

¡Gracias! Esto funcionó –

9

Incidentalmente, el motivo de este extraño comportamiento es que el equipo de seguridad de CLR cambió el verificador justo antes de la entrega de v2, de modo que no se pudo verificar una llamada no virtual en un método virtual de una clase de un método en un clase diferente

Para una explicación más detallada de este problema, consulte mi artículo sobre el tema de hace algunos años.

http://blogs.msdn.com/ericlippert/archive/2005/11/14/why-are-base-class-calls-from-anonymous-delegates-nonverifiable.aspx

Esto es ahora fuera de fecha; arreglamos el compilador para que ahora genere el ayudante para usted.