Почему я не могу конвертировать из List <IScreen>в List <IRenderable>, даже если IScreen реализует IRenderable? - PullRequest
2 голосов
/ 24 мая 2010

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

редактирование: Это код:

interface IRenderable
{
    void Render();
}
interface IScreen : IRenderable
{
}
public List<IScreen> Screens = new List<IScreen>();
List<IRenderable> renderList = new List<IRenderable>();
renderList = ((List<IRenderable>)Screens; // error: cannot convert type IScreen to IRenderable

edit2: кстати, у меня установлен .net 4.0, но ссылка остается System.dll версии 2.0.5.0

Ответы [ 3 ]

2 голосов
/ 24 мая 2010

Полагаю, вы действительно пытаетесь конвертировать из List<IScreen> в List<IRenderable> или что-то подобное.

Вы не можете сделать это вообще до .NET 4 из-за универсальной неизменности . В .NET 4 вы можете сделать это для интерфейсов и делегатов , где это уместно . В частности, вы можете конвертировать из IEnumerable<IScreen> в IEnumerable<IRenderable>. Если вы просто пытаетесь объединить список, это должно быть нормально - вы должны иметь возможность использовать List<T>.AddRange с каждым из ваших списков ... но, опять же, это применяется только в C # 4. Другой вариант в C # 4 будет что-то вроде:

var combined = firstList.Concat<IRenderable>(secondList).ToList();

В качестве примера того, почему это не всегда безопасно (разрешено использование 1018 * в C # 4, безопасно), рассмотрим следующий код:

List<Apple> apples = new List<Apple> { new Apple(...) };
List<Fruit> fruit = apples;
fruit.Add(new Orange());

Теперь список, к которому относится apples, содержит апельсин! Это явно нехорошо с точки зрения безопасности типов.

Как говорит Дриис, если вы можете дать более подробную информацию (например, что у вас есть и что вы хотите), мы сможем помочь больше.

1 голос
/ 24 мая 2010

List<T0> не может быть преобразовано в List<T1>.Вы должны сделать кастинг для каждого элемента списка.Расширение Cast для IEnumarable заключается в следующем:

List<IScreen> Screens = new List<IScreen>();
List<IRenderable> renderList = Screens.Cast<IRenderable>().ToList();
1 голос
/ 24 мая 2010

Вы не даете много деталей. Но давайте предположим, что у вас есть:

IRenderable {}

IScreen : IRenderable {}

private List<IRenderable> ConcatLists(IEnumerable<IRenderable> first, IEnumerable<IRenderable> second) { ... }

Теперь вы не сможете напрямую вызывать метод ConcatLists с помощью IEnumerable в версиях C # до C # 4. Причина этого называется со-и контравариантностью. В Framework 4 IEnumerable объявлен ковариантным, что означает, что он может быть неявно преобразован в IEnumerable, где T имеет меньший тип (IRenderable в вашем случае).

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

Это может быть:

ConcatLists(first.Cast<IRenderable>(), second);

Если объявлено, что «first» относится к типу IRenderable.

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