3 votes

Fonction générique sur une liste de classe dérivée

Je pense que ma question est assez stupide, ou une autre façon de le dire est : Je suis trop perdu dans mon code pour voir une solution pour l'instant. Restez trop longtemps sur un problème, et votre vision devient de plus en plus étroite ><. De plus, je ne suis pas assez bon avec l'héritage, le polymorphisme et ainsi de suite.

Voici l'idée : j'ai plusieurs listes de classes dérivées, et je voudrais appeler des fonctions génériques sur ces listes (accéder et modifier les membres de la classe de base). Je pense qu'il y a quelque chose à faire avec l'héritage, mais je n'arrive pas à le faire fonctionner comme je le souhaite pour le moment .

Voici un exemple très simple de ce que j'ai l'intention de faire :

class Baseclass
{
    public int ID;
    public string Name;
}
class DerivedClass1 : Baseclass
{
}

private void FuncOnBase(List<Baseclass> _collection)
{
    // ...

    foreach (Baseclass obj in _collection)
    {
        ++obj.ID;
    }

    // ...
}
private void FuncTest()
{
    List<DerivedClass1> collection1 = new List<DerivedClass1>();
    collection1.Add(new DerivedClass1() { ID = 1 });
    collection1.Add(new DerivedClass1() { ID = 2 });
    collection1.Add(new DerivedClass1() { ID = 3 });

    FuncOnBase(collection1);   //  ==> forbidden, cannot convert the derived class list to the base class list
}

11voto

Marc Gravell Points 482669

Il faut aimer la variance. A List<DerivedClass1> es no a List<Baseclass> - autrement, FuncOnBase pourrait tenter d'ajouter un Baseclass à la liste, et le compilateur ne l'aurait pas remarqué.

Une astuce consiste à utiliser une méthode générique :

private void FuncOnBase<T>(List<T> _collection) where T : Baseclass
{
    // ...

    foreach (T obj in _collection)
    {
        obj.ID++;
    }

    // ...
}

En ce qui concerne l'exemple que j'ai présenté ci-dessus, notez que nous sommes en mesure d'ajouter une T à la liste ; utile notamment si l'on ajoute l'option T : new() ou passer dans (par exemple) une contrainte params T[] .

Notez également que IEnumerable<T> devient covariant en C# 4.0 / .NET 4.0, de sorte que si vous transmettez uniquement un fichier IEnumerable<Baseclass> (plutôt qu'une liste), cela fonctionnerait "tel quel" :

private void FuncOnBase(IEnumerable<Baseclass> _collection)
{
   ///...
}

2voto

280Z28 Points 49515

Si vous ne faites qu'un foreach déclare FuncOnBase(IEnumerable<Baseclass> collection) que vous pouvez appeler à partir de FuncTest comme ça :

FuncOnBase(collection1.Cast<Baseclass>());

Lorsque vous déclarez une méthode avec un List<T> mais n'utilise que son paramètre IEnumerable<T> vous ajoutez des contraintes API qui ne signifient rien dans votre code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X