Как передать список классов в список интерфейсов? - PullRequest
22 голосов
/ 03 октября 2011

У меня есть такая функция:

DoSomething(List<IMyInterface>)

IMyInterface - это интерфейс, а MyClass - это класс, реализующий этот интерфейс. Класс MyClass: IMyInterface

Я звоню DoSomething(List<MyClass>) и похоже, что это не работает. Как я могу передать список класса в список интерфейса класса в качестве параметра функции? Спасибо!

Ответы [ 3 ]

34 голосов
/ 03 октября 2011

Если ваш код просто повторяет последовательность внутри метода (не добавляя, не удаляя и не обращаясь по индексу), измените ваш метод на один из следующих

DoSomething(IEnumerable<IMyInterface> sequence)
DoSomething<T>(IEnumerable<T> sequence) where T : IMyInterface

Интерфейс IEnumerable<>ковариантный (по состоянию на .NET 4) (первый вариант).Или вы можете использовать последнюю сигнатуру при использовании C # 3.

В противном случае, если вам нужны индексированные операции, преобразуйте список перед его передачей.В вызове у вас может быть

// invocation using existing method signature 
DoSomething(yourList.Cast<IMyInterface>().ToList());

// or updating method signature to make it generic
DoSomething<T>(IList<T> list) where T : IMyInterface

. Последняя подпись позволит вам также поддерживать добавление или удаление в список (видимый на месте вызова), а также позволит вам использоватьсписок без предварительного копирования.

Тем не менее, если все, что вы делаете, это перебираете список в цикле, я бы предпочел метод, принимающий IEnumerable<>.

13 голосов
/ 03 октября 2011

Это вообще небезопасно, потому что списки изменчивы.Предположим, что вы передаете кому-то ссылку на List<MyClass> как List<IMyInterface>, тогда он делает:

void Foo(List<IMyInterface> list)
{
    IMyInterface x = new MyOtherClassWhichAlsoImplementsIMyInterface();
    list.Add(x);
}

Теперь ваш List<MyClass> содержит экземпляр класса, который не является MyClass.Это нарушит безопасность типов.(Как отмечалось в других ответах, вы можете избежать этой проблемы, передав только интерфейс IEnumerable<> List, который обеспечивает доступ только для чтения и поэтому безопасен).

Подробнее см. Using Variance.в интерфейсах для общих коллекций на MSDN .См. Также хорошее резюме ковариации и контравариантности и различных функций C #, которые ее поддерживают .

1 голос
/ 03 октября 2011

Если вам нужно только пройти по списку, объявите метод с IEnumerable.Если вы хотите добавить элементы в список, то, что вы спрашиваете, небезопасно и в результате может не быть разрешено в C #.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...