Коллекции с общими объектами - PullRequest
5 голосов
/ 14 февраля 2011

Существует метод, который принимает список базовых объектов в качестве параметра.

abstract class Base {}
class MyClass:Base {}
//...
void Method(List<Base> list) {}

Когда я вызываю этот метод, я хочу передать список производных объектов.

var derivedList = new List<MyClass>();
Method(derivedList);

Но я не могу этого сделать, потому что набор производных не совпадает с набором базовых объектов.Как лучше всего справляться с этой ситуацией?Сейчас я использую свое расширение .ToBase (), где я создаю новую коллекцию, но я думаю, что есть более хорошее решение.

Спасибо.

Ответы [ 5 ]

11 голосов
/ 14 февраля 2011

Сделайте ваш Method универсальный:

public void Method<T>(List<T> list) where T : Base
{
    //Do your stuff
}
6 голосов
/ 14 февраля 2011

Если метод только читает значения, он может быть объявлен как:

void Method(IEnumerable<Base> list)

таким образом, ваш вызывающий код будет работать нормально в C # 4 / .NET 4 безлюбые изменения.В .NET 3.5 вы могли бы использовать

Method(derivedList.Cast<Base>());

Если ваш метод , добавляющий значения в список, тогда общая ковариация не будет и не будет работать .В конце концов, вы бы не хотели, чтобы к вашему List<MyClass> добавлялась ссылка на экземпляр какого-то другого класса, производного от Base, не так ли?

Создание Methodgeneric (как предложил Клаус) также будет работать в различных ситуациях, но также может сделать код более сложным.Трудно сказать, является ли это хорошим подходом, не зная, что делает ваш метод ... хотя определенно стоит попробовать.

4 голосов
/ 14 февраля 2011

Co- / contra-дисперсия реализована в C # 4.0, что позволит вам напрямую передать List<MyClass> методом, требующим List<Base>, без дополнительной работы.

В C # 3.5 вы можете использовать метод расширения Cast<T>() для преобразования перечислимого одного типа в другой, что позволит вам преобразовать его в базовый тип (со стоимостью приведения для каждой записи). Похоже, вы уже сделали это с помощью метода расширения .ToBase()

0 голосов
/ 14 февраля 2011

Нет лучшего решения, учитывая сигнатуру существующего метода.То, что вы пытаетесь сделать , может быть выполнено с помощью примитивных массивов, и каждый сожалеет об этом.Дело в том, что если вы передадите кому-то List<Base>, то должно быть разрешено для него поместить в Base или что-либо из этого.Но они не могут, потому что это действительно List<MyClass>.Если бы это было разрешено, это сломало бы много вещей.Создание новой коллекции - лучший способ.

0 голосов
/ 14 февраля 2011

Это потому, что List<MyClass> не является List<Base>.

Что вы можете сделать:

Method(derivedList.Cast<Base>().ToList());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...