Question

Pourquoi, avec une contrainte générique sur le paramètre de type T de la classe P de & "; doit hériter de A &" ;, le premier appel aboutit-il mais le second appel échoue avec l'erreur de conversion de type détaillée dans le commentaire:

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>' */
    }
}

La contrainte générique ne devrait-elle pas garantir que List<T> est bien ICollection<A>?

Était-ce utile?

La solution

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

Veuillez consulter C # 4.0: Covariance et Contravariance :

  

Dans cet article, je & # 8217; vais essayer de couvrir un   des innovations C # 4.0. Un de   les nouvelles fonctionnalités est la covariance et   contravariance sur les paramètres de type qui   est maintenant soutenu par des délégués génériques   et interfaces génériques. Commençons par & # 8217; s   voyez ce que signifient ces mots:)

Autres conseils

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 supporte pas la covariance, vous devez donc explicitement convertir la liste en ICollection:

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

Vous avez fortement saisi le paramètre pour DoSecond en tant que type ICollection < A > ;. Malgré le fait que T soit du type A, au moment de la compilation, il n’existe pas de transtypage implicite entre List & Lt; T & Gt; et ICollection < A > ;. Vous devrez soit créer la liste et la convertir en ICollection & Lt; A & Gt; lorsque vous appelez DoSecond ou faites de DoSecond une méthode générique elle-même.

REMARQUE: ce type de distribution implicite doit être pris en charge en C # 4.0, ce qui permettra d'améliorer considérablement la corrélation / la variance par rapport aux offres de C # 3.0.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top