2010-10-29 5 views
11

Pourquoi la compilation suivante?Génériques et diffusion

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 ... } 

Mais cela ne

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

Quelle est l'erreur de compilation ... –

+0

Que dit l'erreur? –

+0

Impossible de convertir l'expression de type 'MyClass ' en type 'MyClass ' – Magpie

Répondre

20

Le travail des interfaces raison est que tout objetpourrait mettre en œuvre IList<T> (à moins qu'il soit connu pour être une instance de un type scellé qui ne l'implémente pas, je suppose) - donc il y a toujours un possible conversion de type de référence à l'interface.

Dans ce dernier cas, le compilateur n'est pas prêt à le faire parce qu'il ne sait pas vraiment que T est bool, en dépit de la déclaration if précédente, il ne sait pas ce que la conversion d'essayer entre MyClass<T> et MyClass<bool> . Les conversions valides aux types génériques sont malheureusement limitées.

Vous pouvez corriger assez facilement:

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

Il est laid, mais il faut travailler ... et au moins dans ce cas, il ne sera pas causer de la boxe.

+0

C'est le cas, merci – Magpie

0

C# 4.0 permet la déclaration de covariance et contravariance sur l'interface paramétrées et types délégués.

+0

Ceci n'essaie pas d'utiliser la variance générique et, de toute façon, la variance générique ne s'applique pas aux arguments de type de type de valeur. –

0

Qu'est-ce qui se passe si vous remplacez

return (MyClass<T>)

avec

return (MyClass<bool>) 
+1

Ensuite, il ne parviendra pas à convertir 'MyClass ' en 'MyClass ' requis par le type de retour. –