2009-10-28 6 views
3

Je pense que ma question est assez bête, ou une autre façon de le dire est: Je suis trop perdu dans mon code pour voir une solution de contournement pour l'instant. Restez trop longtemps sur un problème, et votre vision devient plus étroite et plus étroite> <. De plus je ne suis pas assez bon avec l'héritage, le polymorphisme et doncFonction générique sur une liste de classe dérivée

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 des 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 veux pour l'instant.

Voici un exemple très simple de ce que j'ai l'intention de le 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 
} 

Répondre

11

variance amour Must absolu. Un List<DerivedClass1> est et non un List<Baseclass> - sinon, FuncOnBase pourrait tenter d'ajouter un Baseclass à la liste, et le compilateur ne le repérerait pas.

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 je présenté ci-dessus - noter que nous sommes en mesure d'ajouter un T à la liste; utile en particulier si nous ajoutons la contrainte T : new(), ou transmettez (par exemple) un params T[].

Notez également que IEnumerable<T> devient Covariant en C# 4.0/.NET 4.0, donc si vous avez passé en seulement une IEnumerable<Baseclass> (plutôt qu'une liste), il fonctionne "comme il est":

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

Aime le fait que j'ai deviné que c'était votre message après avoir lu juste 3 mots :) –

+0

Est-ce que je deviens trop prévisible? –

+0

Merci beaucoup, idée très utile :) – Chouppy

2

Si vous re seulement faire un foreach, déclarer FuncOnBase(IEnumerable<Baseclass> collection), que vous pouvez appeler à partir FuncTest comme ceci:

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

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

+0

Woops, merci à vous aussi pour le signaler. – Chouppy

Questions connexes