Невозможно принудительно преобразовать List & lt; List & lt; T & gt; & gt; к IList & lt; Tist & gt; [Дубликат]

Методы внутри org.apache.commons.io.FileUtils также могут быть очень удобными, например :

/**
 * Reads the contents of a file line by line to a List
 * of Strings using the default encoding for the VM.
 */
static List readLines(File file)

69
задан Andrew Kalashnikov 19 January 2012 в 13:38
поделиться

7 ответов

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

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();

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

167
ответ дан Jon Skeet 19 August 2018 в 08:30
поделиться
  • 1
    @Downvoter: Зачем комментировать? – Jon Skeet 19 January 2012 в 13:50
  • 2
    как будто они «все еще в здании»! – Andras Zoltan 19 January 2012 в 14:15
  • 3
    В чем разница между выполнением ковариации и списком List & lt; IFruit & gt; (); затем пропустить по первоначальному списку и добавить каждый элемент в список IFruit? В режиме foreach ... ссылка на объект будет одинаковой, правильно? Итак ... если это правда, для меня не имеет никакого значения, что вы не можете просто напрямую перечислить весь список. ? – Robert Noack 19 December 2014 в 23:01
  • 4
    @RobertNoack: Что вы подразумеваете под «ссылкой на объект»? Ссылка на объект для каждого элемента одинакова, но это не то же самое, что листинг самой ссылки списка. Предположим, вы могли бы использовать ссылку, так что у вас была ссылка типа времени компиляции List<IFruit>, которая на самом деле была ссылкой на List<Apple>. Что бы вы ожидали, если бы вы добавили ссылку Banana к этому List<IFruit>? – Jon Skeet 20 December 2014 в 10:50
  • 5
    @ TrươngQuốcKhánh: Я понятия не имею, как выглядит any вашего кода или у вас есть директива using для System.Linq или то, что вы пытаетесь вызвать, я не уверен, как вы ожидаете, что я смогу помочь. Я предлагаю вам сделать больше исследований, и если вы все еще застряли, задайте вопрос с помощью примера Minimal, Complete и Verifiable . – Jon Skeet 30 July 2017 в 06:54

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

List<IDic> casted = input.Cast<IDic>().ToList() выполнит трюк.

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

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

4
ответ дан Andras Zoltan 19 August 2018 в 08:30
поделиться
  • 1
    Cast возвращает IEnumerable<T>, а не List<T> - и нет, ковариация не будет разрешать это преобразование, потому что это будет небезопасно - см. мой ответ. – Jon Skeet 19 January 2012 в 13:41
  • 2
    Со страницы, на которую вы ссылались: «Только типы интерфейсов и типы делегатов могут иметь параметры типа варианта». – Jon Skeet 19 January 2012 в 13:44
  • 3
    @Jon - я понял, что ToList() отсутствует, прежде чем читать ваш комментарий; но да, как вы показали, конечно, Ковариация не сработает! Doh! – Andras Zoltan 19 January 2012 в 13:44
  • 4
    Правильно. Ковариация может по-прежнему помогать, так как это означает, что вам не нужен вызов Cast в .NET 4, если вы указываете аргумент типа ToList. – Jon Skeet 19 January 2012 в 13:45

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

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

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

0
ответ дан Kent Aguilar 19 August 2018 в 08:30
поделиться
  • 1
    Проблема заключается в том, что это копия списка, большую часть времени вы хотите выполнять операции в исходном списке – rolls 22 January 2017 в 07:33
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
1
ответ дан Marc Messing 19 August 2018 в 08:30
поделиться

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

List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
1
ответ дан musefan 19 August 2018 в 08:30
поделиться

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

0
ответ дан Piotr Auguscik 19 August 2018 в 08:30
поделиться
  • 1
    Любые комментарии, почему ниспровергаются, поскольку общий смысл такой же, как и все другие ответы? – Piotr Auguscik 19 January 2012 в 13:43
  • 2
    Я предполагаю, что вы зашли вниз, потому что вы сказали, что создать только новый список можно только, но другие отправили на обратное ... но не мое понижение) – musefan 19 January 2012 в 13:46
  • 3
    Ну, они создают новые списки, но не с новым оператором, который не меняет того факта, что они делают. – Piotr Auguscik 19 January 2012 в 13:47
  • 4
    Да, я полагаю, они это делают – musefan 19 January 2012 в 13:49

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

Например:

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

Вместо:

public void ProcessIDic(List<IDic> list)
{
   // Implementation
}
3
ответ дан Ɖiamond ǤeezeƦ 19 August 2018 в 08:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: