2010-10-29 17 views
11

¿Por qué se compila la siguiente información?Genéricos y Fundición

public IList<T> Deserialize<T>(string xml) 
{    
    if (typeof(T) == typeof(bool)) 
     return (IList<T>)DeserializeBools(xml); 

    return null; 
} 

private static IList<bool> DeserializeBool(string xml) { ... do stuff ... } 

pero esto no

public MyClass<T> GetFromDb<T>(string id) 
{ 
    if (typeof(T) == typeof(bool)) 
     return (MyClass<T>)GetBoolValue(id); <-- compiler error here 

    return null; 
} 

private static MyClass<bool> GetBoolValue(string id) { ... do stuff ... } 
+5

¿Cuál es el error de compilación ... –

+0

¿Qué dice el error? –

+0

No se puede expresar el tipo 'MyClass ' para escribir 'MyClass ' – Magpie

Respuesta

20

La obra razón de interfaces es que cualquier objeto podría aplicar IList<T> (a menos que sea conocido por ser una instancia de un tipo sellado que no lo implementa, supongo) - por lo que siempre hay un posible conversión de tipo de referencia a la interfaz.

En este último caso, el compilador no está dispuesto a hacer eso, ya que no sabe realmente que es T bool, a pesar de la if declaración anterior, por lo que no se sabe lo que la conversión a tratar entre MyClass<T> y MyClass<bool> . Las conversiones válidas a los tipos genéricos son bastante limitadas, lamentablemente.

se puede arreglar con bastante facilidad:

return (MyClass<T>)(object) GetBoolValue(id); 

Es feo, pero debería funcionar ... y al menos en este caso no va a causar ningún boxeo.

+0

Sí, gracias – Magpie

0

C# 4.0 permite la declaración de covarianza y contravarianza en parametrizados interfaz y delegar tipos.

+0

Esto no está tratando de usar la varianza genérica, y de todos modos la varianza genérica no se aplica a los argumentos de tipo de tipo de valor. –

0

¿Qué pasa si se reemplaza

return (MyClass<T>)

con

return (MyClass<bool>) 
+1

Entonces no podrá convertir de 'MyClass ' al 'MyClass ' requerido por el tipo de devolución. –