2009-07-31 5 views
3

Pourquoi, avec une contrainte générique sur le paramètre de type T de «doit hériter de A», le premier appel réussit-il mais le second échoue avec l'erreur de conversion de type détaillée dans le commentaire :Erreur de conversion de type C# malgré la contrainte générique

abstract class A { } 

static class S 
{ 
    public static void DoFirst(A argument) { } 
    public static void DoSecond(ICollection<A> argument) { } 
} 

static class P<T> 
    where T : A, new() 
{ 
    static void Do() 
    { 
     S.DoFirst(new T());    // this call is OK 

     S.DoSecond(new List<T>());  // this call won't compile with: 

     /* cannot convert from 'System.Collections.Generic.List<T>' 
      to 'System.Collections.Generic.ICollection<A>' */ 
    } 
} 

pas Si la contrainte générique faire en sorte que List<T> est en effet ICollection<A>?

+1

Fermeture comme dupe - s'il vous plaît voir http://stackoverflow.com/questions/981570/c-no-implict-conversion-from-classchild-to-classbase –

Répondre

7

Ceci est un exemple de l'absence de C# de covariance sur les types génériques (C# ne supporte la covariance de tableau). C# 4 ajoutera cette fonctionnalité aux types d'interface et mettra également à jour plusieurs types d'interface BCL pour la prendre en charge.

S'il vous plaît voir C# 4.0: Covariance and Contravariance:

Dans cet article, je vais essayer de couvrir un des C# 4.0 innovations. L'une des nouvelles fonctionnalités est covariance et contravariance sur les paramètres de type que est maintenant pris en charge par les délégués génériques et les interfaces génériques. Tout d'abord voyons ce que ces mots signifient :)

+4

Cela ne changera pas dans C# 4.0. 'IList ' et 'ICollection ' sont _not covariant_. Donc, même si C# 4.0 va ajouter un support pour la covariance de type, ce cas particulier ne fonctionnera pas. –

+0

Pavel, vous semblez être confus ici. Les types en jeu ne sont PAS IList et ICollection ... ils sont Liste (le type concret, pas l'interface) et ICollection . Une liste est ABSOLUMENT une ICollection , et cela les rend covariant. Vous avez posté votre commentaire dans TROIS messages, et apparemment downvoted deux d'entre eux ... sur la base du mauvais type ... ce n'est pas IList , sa Liste ! – jrista

0

La contrainte n'a aucun effet sur le problème; le problème est que vous passez une liste dans un paramètre qui nécessite ICollection - C# ne prend pas en charge covariance de sorte que vous devez jeter explicitement la liste à un ICollection:

S.DoSecond((ICollection<A>) new List<T>());  // this call will be happy 
+1

Le problème n'est pas incompatibilité 'IList' /' ICollection', le problème est de type discordance d'argument. –

0

Vous avez fortement typé le paramètre pour DoSecond comme type ICollection <A>. Malgré le fait que T est de type A, au moment de la compilation, il n'y a pas implicite coulé entre la liste <T> et ICollection <A>. Vous devrez soit créer la liste et l'attribuer à ICollection <A> lorsque vous appelez DoSecond, soit faire de DoSecond une méthode générique elle-même.

REMARQUE: ce type de distribution implicite doit être pris en charge dans C# 4.0, ce qui offre une meilleure co/contravariance par rapport à ce que propose C# 3.0.

Questions connexes