2010-07-03 9 views
5

Creo que debo estar perdiendo algo, por qué no puedo compilar este:¿Por qué no puedes convertir un genérico abierto limitado al tipo restringido?

class Foo<T> where T : Bar 
{ 
    T Bar; 
} 

abstract class Bar 
{ } 

class MyBar : Bar 
{ } 

static void Main(string[] args) 
{ 
    var fooMyBar = new Foo<MyBar>(); 
    AddMoreFoos(fooMyBar); 
} 

static void AddMoreFoos<T>(Foo<T> FooToAdd) where T : Bar 
{ 
    var listOfFoos = new List<Foo<Bar>>(); 
    listOfFoos.Add(FooToAdd); //Doesn't compile 
    listOfFoos.Add((Foo<Bar>)FooToAdd); //doesn't compile 
} 

Respuesta

9

Usted es hacer las cosas un poco más confuso de lo que necesitan ser mediante el uso de una lista aquí ... es más fácil de ver el efecto de esta manera:

// This won't compile 
Foo<Bar> fooBar = new Foo<MyBar>(); 

Dado que este no se compila , no es de extrañar entonces que no se puede agregar un Foo<MyBar> a un List<Foo<Bar>>

¿Por qué no es un Foo<MyBar> un Foo<Bar>? Porque las clases genéricas no son covariantes.

varianza genérica no se introdujo en C# 4 - y sólo funciona para las interfaces y delegados. Por lo que podría (en C# 4) hacer:

IEnumerable<MyBar> x = new List<MyBar>(); 
IEnumerable<Bar> y = x; 

pero no se podía hacer:

IList<MyBar> x = new List<MyBar>(); 
IList<Bar> y = x; 

que tienen toda una charla sobre la variación que se puede descargar desde el NDC 2010 video site - sólo la búsqueda de " diferencia".

3

No compila porque si se va a llamar a su método con un Foo<int> entonces la llamada se producirá un error: usted está tratando para asumir un tipo específico para su parámetro genérico.

Lo que necesita es usar var listOfFoos = new List<Foo<T>>() en su lugar, entonces el Add debería funcionar.

(EDITAR: igualmente, el elenco funcionaría si usó Foo<T> - pero todavía no puede suponer en su código que T es).

+0

'si tuviera que llamar a su método con un Foo entonces la llamada fallará' => pero esta llamada no se compilará debido a la limitación genérica, donde T: bar, ¿no? Sin embargo, +1 para la nueva lista >() ya que esto realmente resuelve mi problema real. –

+0

Buen punto en la restricción. Confundido sobre por qué aceptaste la otra respuesta si resolví tu problema aunque ... (Jon Skeet o no! ;-)) –

Cuestiones relacionadas