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





3 Answers

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. Quel est le risque que le compilateur autorise la conversion de List<DerivedClass> en List<BaseClass> ?

Cette question est posée presque tous les jours.

Une List<Mammal> ne peut pas être convertie en une List<Animal> car vous pouvez placer un lézard dans une liste d’animaux . Une List<Mammal > ne peut pas être convertie en une List<Giraffe> car il pourrait y avoir déjà un tigre dans la liste .

Par conséquent, List<T> doit être invariant dans T.

Cependant, List<Mammal> peut être converti en IEnumerable<Animal> (à partir de C # 4.0) car il n’existe aucune méthode sur IEnumerable<Animal> qui ajoute un lézard. IEnumerable<T> est covariant dans T.

documentation visual studio

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



Lorsque vous avez une classe dérivée d'une classe de base, tous les conteneurs de ces classes ne sont pas automatiquement dérivés. Vous ne pouvez donc pas simplement lancer une List<Derived> dans une List<Base> .

Utilisez .Cast<T>() pour créer une nouvelle liste où chaque objet est renvoyé à la classe de base:

List<MyDerived> list1 = new List<MyDerived>();
List<MyBase> list2 = list1.Cast<MyBase>().ToList();

Notez qu'il s'agit d'une nouvelle liste, et non d'une version de distribution de votre liste d'origine. Les opérations sur cette nouvelle liste ne seront donc pas reflétées dans la liste d'origine. Les opérations sur les objets contenus refléteront cependant.




Une solution que j'ai utilisée consistait à créer une classe d'extension:

public static class myExtensionClass 
{
    public void doSomething<T>(List<BaseClass> bc) where T: BaseClass
    {
        // do something with bc
    }
}

Il utilise des termes génériques, mais quand vous l'appelez, vous n'avez pas à spécifier la classe puisque vous avez déjà dit au compilateur que le type est le même que celui de la classe étendue.

Vous appelez ça comme ça:

List<DerivedClass> lst = new List<DerivedClass>();
lst.doSomething();



Related


Tags

c#