Question

Je pense que ma question est plutôt idiote, ou d’une autre façon de la formuler: je suis trop perdu dans mon code pour voir une solution de contournement pour le moment. Restez trop longtemps sur un problème, et votre vision devient de plus en plus étroite & Gt; & Lt ;. De plus, je ne suis pas assez bon avec l'héritage, le polymorphisme et ainsi

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

Voici un exemple très simple de ce que je compte 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
}
Était-ce utile?

La solution

Je dois aimer la variance. Un List<DerivedClass1> n’est pas un List<Baseclass> - sinon, FuncOnBase pourrait essayer d’ajouter un Baseclass à la liste, sans que le compilateur le repère.

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 pouvons ajouter un T à la liste; utile en particulier si nous ajoutons la contrainte T : new(), ou si nous transmettons (par exemple) un params T[].

Notez également que IEnumerable<T> devient une covariante dans C # 4.0 / .NET 4.0. Par conséquent, si vous transmettez simplement un IEnumerable<Baseclass> (plutôt qu'une liste), cela fonctionnera & "tel quel &"; :

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

Autres conseils

Si vous ne faites qu'un foreach, déclarez FuncOnBase(IEnumerable<Baseclass> collection), vous pouvez appeler à partir de FuncTest comme suit:

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

Lorsque vous déclarez une méthode avec un paramètre List<T> mais n'utilisez que ses IEnumerable<T> fonctionnalités, vous ajoutez des contraintes d'API qui ne veulent rien dire dans votre code.

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