Список <T>в список <Interface> - PullRequest
91 голосов
/ 19 января 2012
public interface IDic
{
    int Id { get; set; }
    string Name { get; set; }
}
public class Client : IDic
{

}

Как я могу разыграть List<Client> на List<IDic>?

Ответы [ 7 ]

210 голосов
/ 19 января 2012

Вы не можете разыграть это (сохранение ссылочной идентичности) - это было бы небезопасно. Например:

public interface IFruit {}

public class Apple : IFruit {}
public class Banana : IFruit {}

...

List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());

// Eek - it's a banana!
Apple apple = apples[0];

Теперь вы можете преобразовать List<Apple> в IEnumerable<IFruit> в .NET 4 / C # 4 из-за ковариации, но если вы хотите List<IFruit>, вам придется создать новый список , Например:

// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();

// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();

Но это , а не - это то же самое, что и приведение исходного списка - потому что теперь есть два отдельных списка. Это безопасно, но вы должны понимать, что изменения, внесенные в один список , не будут видны в другом списке. (Конечно, будут видны модификации объектов , на которые ссылаются списки.)

5 голосов
/ 19 января 2012

Итератор Cast и .ToList ():

List<IDic> casted = input.Cast<IDic>().ToList() сделают свое дело.

Изначально я сказал, что ковариация будет работать - но, как правильно заметил Джон;нет, не будет!

И изначально я тоже тупо перестал ToList() звонить

4 голосов
/ 27 января 2016

У меня тоже была эта проблема, и после прочтения ответа Джона Скита я изменил свой код, используя List<T> для использования IEnumerable<T>.Хотя это не отвечает на первоначальный вопрос ОП: Как я могу разыграть List<Client> на List<IDic>, это избавляет от необходимости делать это и, таким образом, может помочь другим, кто столкнулся с этой проблемой.Это, конечно, предполагает, что код, который требует использования List<IDic>, находится под вашим контролем.

Например:

public void ProcessIDic(IEnumerable<IDic> sequence)
{
   // Implementation
}

Вместо:

public void ProcessIDic(List<IDic> list)
{
   // Implementation
}
2 голосов
/ 19 января 2012
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
2 голосов
/ 19 января 2012

Если вы можете использовать LINQ, то вы можете сделать это ...

List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
0 голосов
/ 04 января 2017

В .Net 3.5 вы можете делать следующее:

List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());

Конструктор для List в этом случае принимает IEnumerable.
список хотя можно конвертировать только в IEnumerable. Даже если myObj может быть преобразовано в ISomeInterface, тип IEnumerable не может быть преобразован в IEnumerable.

0 голосов
/ 19 января 2012

Это возможно только путем создания нового List<IDic> и передачи всех элементов.

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