В C #, почему объект List не может быть сохранен в переменной List

Кажется, что объект List не может быть сохранен в переменной List в C # и не может быть явно указан таким образом.

List sl = new List(); List ol; ol = sl; 

результаты не могут неявно преобразовать тип System.Collections.Generic.List в System.Collections.Generic.List

А потом…

 List sl = new List(); List ol; ol = (List)sl; 

результаты не могут преобразовать тип System.Collections.Generic.List в System.Collections.Generic.List

Конечно, вы можете сделать это, вытащив все из списка строк и вернув его по одному за раз, но это довольно запутанное решение.

    Подумайте об этом таким образом, если бы вы сделали такой отбор, а затем добавили в список объект типа Foo, список строк больше несовместим. Если вы хотите перебрать первую ссылку, вы получите исключение classа, потому что, как только вы нажмете на экземпляр Foo, Foo не может быть преобразован в строку!

    В качестве примечания, я думаю, было бы более важно, можете ли вы сделать обратный перевод:

     List ol = new List(); List sl; sl = (List)ol; 

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

    Кто-нибудь знает или может проверить, является ли такой актер законным в C #?

    Если вы используете .NET 3.5, посмотрите на метод Enumerable.Cast. Это метод расширения, поэтому вы можете вызвать его непосредственно в списке.

     List sl = new List(); IEnumerable ol; ol = sl.Cast(); 

    Это не совсем то, что вы просили, но должен сделать трюк.

    Изменить: Как отметил Зооба, вы можете вызвать ol.ToList (), чтобы получить список

    Вы не можете вводить между типичными типами с различными параметрами типа. Специализированные общие типы не являются частью одного и того же дерева наследования и поэтому не связаны между собой.

    Для этого pre-NET 3.5:

     List sl = new List(); // Add strings to sl List ol = new List(); foreach(string s in sl) { ol.Add((object)s); // The cast is performed implicitly even if omitted } 

    Использование Linq:

     var sl = new List(); // Add strings to sl var ol = new List(sl.Cast()); // OR var ol = sl.Cast().ToList(); // OR (note that the cast to object here is required) var ol = sl.Select(s => (object)s).ToList(); 

    Причина в том, что общий class, такой как List<> , для большинства целей обрабатывается как обычный class. например, когда вы говорите List() компилятор говорит ListString() (который содержит строки). [Технический фолк: это очень простая англо-исландская версия того, что происходит]

    Следовательно, очевидно, что компилятор не может быть достаточно умным, чтобы преобразовать ListString в объект ListObject, отбрасывая элементы его внутренней коллекции.

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

    Это имеет много общего с ковариацией, например, общие типы рассматриваются как параметры, и если параметры не будут корректно разрешены для более конкретного типа, то операция завершится с ошибкой. Следствием такого является то, что вы действительно не можете использовать более общий тип, такой как объект. И, как указано Rex, объект List не будет конвертировать каждый объект для вас.

    Вместо этого вы можете попробовать использовать ff-код:

     List sl = new List(); //populate sl List ol = new List(sl); 

    или:

     List ol = new List(); ol.AddRange(sl); 

    ol будет (теоретически) скопировать все содержимое sl без проблем.

    Да, вы можете, от .NET 3.5:

     List sl = new List(); List ol = sl.Cast().ToList(); 

    Майк – Я считаю, что контравариантность не допускается на C #

    Дополнительную информацию см. В разделе « Распределение параметров типового типа» в CLR .

    Я думаю, что это (контравариантность) будет фактически поддерживаться в C # 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

    Это на самом деле так, что вы не пытаетесь помещать какой-либо нечетный «объект» в ваш вариант списка «ol» (как может показаться List ) – потому что тогда ваш код будет разбиваться (потому что список действительно является List и будут принимать только объекты типа String). Вот почему вы не можете передавать свою переменную в более общую спецификацию.

    На Java это наоборот, у вас нет дженериков, и вместо этого все это List of object во время выполнения, и вы действительно можете набить какой-либо странный объект в свой предположительно строго типизированный List. Найдите «Reified generics», чтобы увидеть более широкое обсуждение проблемы java …

    Такая ковариация на дженериках не поддерживается, но вы можете на самом деле сделать это с помощью массивов:

     object[] a = new string[] {"spam", "eggs"}; 

    C # выполняет проверки времени выполнения, чтобы вы не могли помещать, скажем, int в a .

    Вот еще одно пред-.NET 3.5 решение для любого IList, содержимое которого может быть введено неявно.

     public IList ConvertIList(IList list) where D : B { List newList = new List(); foreach (D item in list) { newList.Add(item); } return newList; } 

    (Основываясь на примере Зооба)

    У меня есть:

     private List Leerlingen = new List(); 

    И я собирался заполнить его данными, собранными в List Что, наконец, сработало для меня, было следующим:

     Leerlingen = (List)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast(); 

    .Cast его к типу, который вы хотите получить IEnumerable из этого типа, затем IEnemuerable в List<> вы хотите.

    Mm, благодаря предыдущим комментариям, я нашел два способа узнать это. Первый из них получает строковый список элементов и затем переводит его в список объектов IEnumerable:

     IEnumerable ob; List st = new List(); ob = st.Cast(); 

    Второй способ – исключить тип объекта IEnumerable, просто приведя строку к типу объекта, а затем используя функцию «toList ()» в том же предложении:

     List st = new List(); List ob = st.Cast().ToList(); 

    Мне больше нравится второй путь. Надеюсь, это поможет.

     List sl = new List(); List ol; ol = new List(sl); 
    Давайте будем гением компьютера.