2010-05-13 6 views
7

Tengo una clase abstracta llamada Agrupación. Tengo una subclase llamada GroupingNNA.Problema con la herencia y Lista <>

public class GroupingNNA : Grouping { 
    // blah blah blah 
} 

Tengo una lista que contiene elementos de tipo GroupingNNA, pero en realidad es declarado para contener elementos de tipo de agrupación.

List<Grouping> lstGroupings = new List<Grouping>(); 
lstGroupings.Add(
    new GroupingNNA { fName = "Joe" }); 
lstGroupings.Add(
    new GroupingNNA { fName = "Jane" }); 

El problema: La siguiente consulta LINQ sopla en mí por el hecho de que lstGroupings se declara como Lista < Agrupación> FName y es una propiedad de GroupingNNA, no agrupar.

var results = from g in lstGroupings 
       where r.fName == "Jane" 
       select r; 

Ah, y esto es un error del compilador, no un error de tiempo de ejecución. Gracias de antemano por cualquier ayuda en este caso!

Más información: Aquí está el método real que no compilará. OfType() corrigió la consulta LINQ, pero al compilador no le gusta el hecho de que estoy tratando de devolver el tipo anónimo como una lista < Agrupando>.

private List<Grouping> ApplyFilterSens(List<Grouping> lstGroupings, string fSens) { 

    // This works now! Thanks @Lasse 
    var filtered = from r in lstGroupings.OfType<GroupingNNA>() 
       where r.QASensitivity == fSens 
       select r; 

    if (filtered != null) { 
    **// Compiler doesn't like this now** 
    return filtered.ToList<Grouping>(); 
    } 
    else 
    return new List<Grouping>(); 
    } 

Respuesta

6

Probar:

= from g in lstGroupings.OfType<GroupingNNA>() 

esto evitará cualquier elemento que no sean de tipo GroupingNNA, y también hacer el uso del compilador GroupingNNA como el tipo de g.

En respuesta a los comentarios y a las preguntas editadas. No, el compilador sin duda no será feliz con su colección cambiado, pero se puede arreglar eso:

return new List<Grouping>(filtered.ToArray()); 

Esto se basa en el hecho de que las matrices en .NET son co/contra-variante, que permite que el compilador trate GroupingNNA[] como Grouping[] para el constructor.

Además, no es necesario el cheque if (filtered != null), obtendrá una colección de filtered, simplemente no puede producir ningún elemento, pero siempre habrá filtered no null.

Esto significa que su código puede ser escrito como:

var filtered = from r in lstGroupings.OfType<GroupingNNA>() 
       where r.QASensitivity == fSens 
       select r; 
return new List<Grouping>(filtered.ToArray()); 

o incluso sólo:

return new List<Grouping>((from r in lstGroupings.OfType<GroupingNNA>() 
          where r.QASensitivity == fSens 
          select r).ToArray()); 

o incluso menor si se le cae la sintaxis de LINQ:

return new List<Grouping>((lstGroupings.OfType<GroupingNNA>() 
    .Where(r => r.QASensitivity == fSens).ToArray()); 

Tenga en cuenta que Por supuesto, puede usar OfType para ir al revés:

return filtered.OfType<Grouping>().ToList(); 

no debe haber grandes diferencias de rendimiento entre las diferentes formas aquí, en caso de duda, mídelo, pero yo iría con lo que encuentre más fácil de leer y entender.

+0

¡Gracias! Estoy un paso más cerca ahora. Sin embargo, el compilador no está contento ahora porque estoy tratando de devolver el tipo anónimo como una lista < Grouping>. Haré una edición de mi publicación original con más código para que pueda ver de lo que estoy hablando. Gracias de nuevo. – Jagd

5

Llamar a ToList<AnotherType>() se está volviendo a poner en el mismo barco que antes: la covarianza/contravariencia genérica no es compatible, por ejemplo. List<Type> no es compatible ni convertible a/desde List<SubType>.

Es necesario utilizar filtered.OfType<Grouping>().ToList(); - el primero le lleva de nuevo a una IEnumerable<Grouping> en lugar de un IEnumerable<GroupingNNA>, y luego ToList simplemente convierte la IEnumerable a un List del mismo tipo genérico.

+0

.NET 2.xa 3.5 Las listas genéricas son invariables. Esto es por tu propio bien. Mire a .NET 4.0 para soporte de tipados más sueltos en genéricos –

Cuestiones relacionadas