c# summary - Impossible de convertir de la liste <DerivedClass> en liste <BaseClass>




3 Answers

C'est parce que List<T> est in-variant , pas co-variant , donc vous devriez changer pour IEnumerable<T> qui supporte le co-variant , ça devrait fonctionner:

IEnumerable<BaseClass> bcl = new List<DerivedClass>();
public void doSomething(IEnumerable<BaseClass> bc)
{
    // do something with bc
}

Informations sur la co-variante en générique

documentation visual

J'essaie de passer une liste de DerivedClass à une fonction qui prend une liste de BaseClass , mais j'obtiens l'erreur:

cannot convert from 
'System.Collections.Generic.List<ConsoleApplication1.DerivedClass>' 
to 
'System.Collections.Generic.List<ConsoleApplication1.BaseClass>'

Maintenant, je pourrais List<DerivedClass> ma List<DerivedClass> en une List<BaseClass> , mais je ne me sens pas à l’aise à moins de comprendre pourquoi le compilateur ne le permet pas.

Les explications que j'ai trouvées ont simplement dit que cela violait en quelque sorte la sécurité de type, mais je ne le vois pas. Quelqu'un peut m'aider?

Quel est le risque que le compilateur autorise la conversion de List<DerivedClass> en List<BaseClass> ?

Voici mon SSCCE:

class Program
{
    public static void Main()
    {
        BaseClass bc = new DerivedClass(); // works fine
        List<BaseClass> bcl = new List<DerivedClass>(); // this line has an error

        doSomething(new List<DerivedClass>()); // this line has an error
    }

    public void doSomething(List<BaseClass> bc)
    {
        // do something with bc
    }
}

class BaseClass
{
}

class DerivedClass : BaseClass
{
}



Le comportement que vous décrivez est appelé covariance - si A est B , alors List<A> est List<B> .

Cependant, pour les types mutables comme List<T> , cela est fondamentalement dangereux.

Si cela avait été possible, la méthode pourrait ajouter un new OtherDerivedClass() à une liste qui ne peut contenir que DerivedClass .

La covariance est sûre sur les types immuables, même si .Net ne le prend en charge que dans les interfaces et les délégués.
Si vous modifiez le paramètre List<T> en IEnumerable<T> , cela fonctionnera




Si tu pouvais écrire

List<BaseClass> bcl = new List<DerivedClass>(); 

vous pourriez appeler

var instance = new AnotherClassInheritingFromBaseClass();
bc1.Add(instance);

Ajout d'une instance qui n'est pas une DerivedClass à la liste.




Related

c#

Tags

c#