Как преобразовать универсальный Список <T> в основанный на интерфейсе Список <T>

Я уверен, что пропускаю что-то простое, однако я пытаюсь преобразовать список со строгим контролем типов объектов что вся реализация интерфейс в к списку того интерфейсного типа.

Ниже образец для демонстрации ошибки:

public void ExampleCode(){
    List<Cube> cubes = new List<Cube>();
    List<Shape> allShapes;
    allShapes = cubes;//Syntax Error
    allShapes = (List<Shape>)cubes;//Syntax Error  
}

public class Cube : Shape
{
    public int ID { get; set; }
    public int Sides { get; set; }
}

public interface Shape
{
  int ID { get; set; }
  int Sides { get; set; }
}
7
задан Donnelle 11 October 2015 в 21:37
поделиться

7 ответов

Вместо этого попробуйте:

allShapes = cubes.Cast<Shape>().ToList();

Для этого вам понадобится .NET 3.5. Я считаю, что метод расширения Cast можно найти в System.Linq.

13
ответ дан 6 December 2019 в 07:06
поделиться

Что вы имеете в виду под значениями keySet , entureSet и ? Если вы имеете в виду внутренние поля HashMap , то вы не должны смотреть на них и не должны заботиться о них. Они используются для кэширования.

Например, в виртуальной машине Java 6, которая использует keySet () , реализуется следующим образом:

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null ? ks : (keySet = new KeySet()));
}

Поэтому тот факт, что keySet имеет значение null , не имеет значения. keySet () (метод) никогда не возвращает null .

То же самое справедливо для значений entureSet () и () .

-121--3286626-

Невозможно. Поскольку List < T > и ILIst < T > поддерживают только параметры инвариантного типа. Это до T и используется для входных и выходных параметров (например, возвращаемых значений). В противном случае можно нарушить безопасность типа.

Другие интерфейсы (например, IEntumerable < T > ) действительно допускают некоторое отклонение.

См. блог Эрика Липперта « Fabulous Adventures In Coding » для обсуждения контра- и ко-дисперсии. В частности, тэг « Ковариация и контравариантность ».

Отредактируйте, только что добавленные в блог «C # Часто задаваемые вопросы»: Часто задаваемые вопросы по ковариации и контравариантности

-121--3791941-

Вы не можете сделать это, поскольку, показав таким образом, вы потенциально можете потерять безопасность любого типа. Например, приведение List < Shape > к List < object > приведет к тому, что объекты любого типа могут быть добавлены в список, что будет совершенно непоследовательно.

2
ответ дан 6 December 2019 в 07:06
поделиться

Вы также можете:

allShapes = cubes.ConvertAll(x => (Shape)x);

Или, если вы делаете это в .NET 2.0:

allShapes = cubes.ConvertAll<Shape>(delegate(Cube c){
    return (Shape)c;
});
0
ответ дан 6 December 2019 в 07:06
поделиться

Это работает, если вы определяете allShapes как IEnumerable

в C # 4.0 вы можете просто назначить allshapes = cubes

Для C # 3.5 вы можете использовать allShapes = cubes.Select (c => ((Shape) c));

Но в любом случае вам нужно использовать IEnumerable вместо List

0
ответ дан 6 December 2019 в 07:06
поделиться

Вы не можете. Поскольку List и ILIst поддерживают только параметры инвариантного типа. Это связано с тем, что T используются как для входных, так и для выходных параметров (например, возвращаемых значений). В противном случае вы можете нарушить безопасность типа.

Другие интерфейсы (например, IEntumerable ) допускают некоторую вариативность.

См. Блог Эрика Липперта « Fabulous Adventures In Coding » для обсуждения контра- и ковариантности. В частности, тег « Ковариация и контравариантность ».

Редактировать, только что добавлено в блог «Часто задаваемые вопросы по C #»: Часто задаваемые вопросы о ковариации и контравариантности

6
ответ дан 6 December 2019 в 07:06
поделиться

То, что вы имеете в виду, называется общей ковариацией и не поддерживается в C # 3. Тем не менее, она поддерживается в C # 4 (.NET 4 / VS 2010), и вы можете узнать больше об этом здесь:

Дисперсия в Общие интерфейсы

Сказав это, IList не является ковариантным (потому что он и принимает, и предоставляет T ). IEnumerable , с другой стороны, ковариантен (потому что он не принимает T ).

4
ответ дан 6 December 2019 в 07:06
поделиться

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

Другие интерфейсы (например, IEntumerable < T > ) действительно допускают некоторое отклонение.

См. блог Эрика Липперта « Fabulous Adventures In Coding » для обсуждения контра- и ко-дисперсии. В частности, тэг « Ковариация и контравариантность ».

Изменить, только что добавлено в блог «C # Часто задаваемые вопросы»: Часто задаваемые вопросы по ковариации и контравариантности

-121--3791941-
$('#element').click(function() {
   if($('#radio_button').is(':checked')) { alert("it's checked"); }
});
-121--1789499-

Нельзя разделять списки типов, даже если сами типы являются конвертируемыми. Необходимо создать новый список и заполнить его либо путем итерации исходного списка, либо с помощью команды ConvertAll. Пример кода см. в http://www.dev102.com/2008/05/15/how-to-convert-listt1-to-listt2/ .

0
ответ дан 6 December 2019 в 07:06
поделиться
Другие вопросы по тегам:

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