2009-10-28 2 views
3

Я чувствую, что мой вопрос довольно глупый, или другой способ выразить это: я слишком потерялся в своем коде, чтобы увидеть обходной путь. Остановитесь слишком долго на проблеме, и ваше зрение становится уже и более узким> <. Плюс я не достаточно хорош с наследованием, полиморфизмом и такОбщая функция в списке производного класса

Вот идея: у меня есть несколько списков производного класса, и я бы хотел назвать общие функции в этих списках (присоединяющиеся и изменяющие члены базового класса). Я чувствую, что есть какое-то отношение к наследованию, но мне пока не удается заставить его работать так, как я хочу.

Вот очень простой пример того, что я намерен сделать:

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 
} 

ответ

11

Готта любовь дисперсия. A List<DerivedClass1> является не a List<Baseclass> - в противном случае, FuncOnBase может попытаться добавить в список Baseclass, а компилятор не обнаружит его.

Один трюк заключается в использовании универсального метода:

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

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

    // ... 
} 

В терминах примера я представил выше - обратите внимание, что мы можем добавить T в список; полезно, в частности, если мы добавим ограничение T : new() или передадим (например) params T[].

Заметим также, что IEnumerable<T> становится ковариантны в C# 4.0/.NET 4.0, так что если вы прошли в просто IEnumerable<Baseclass> (а не список) он будет работать «как есть»:

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

Должен любить тот факт, что я догадался, что это был ваш пост после прочтения всего 3 слов :) –

+0

Я становлюсь слишком предсказуемым? –

+0

Большое спасибо, очень полезная идея :) – Chouppy

2

Если вы» повторно только делает foreach, объявить FuncOnBase(IEnumerable<Baseclass> collection), которые можно вызывать из FuncTest так:

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

При объявлении метода с параметром List<T>, но только использовать его IEnumerable<T>, вы добавляете ограничения API, которые ничего не означают в вашем коде.

+0

Woops, спасибо вам тоже за то, что указали это. – Chouppy

Смежные вопросы