Почему я не могу конвертировать из List<IScreen> в List<IRenderable>, даже если IScreen реализует IRenderable?
Довольно понятный вопрос, рад за любой ответ. Для меня это не имеет смысла. Меня не волнует потеря информации. Я просто хочу объединить все мои списки, которые как-то наследуют 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 ответа
Вы не даете много деталей. Но давайте предположим, что у вас есть:
IRenderable {}
IScreen : IRenderable {}
private List<IRenderable> ConcatLists(IEnumerable<IRenderable> first, IEnumerable<IRenderable> second) { ... }
Теперь вы не сможете напрямую вызывать метод ConcatLists с помощью IEnumerable
Если вы хотите вызвать такой метод в C#3, вы можете использовать метод расширения, чтобы помочь вам.
Это может быть:
ConcatLists(first.Cast<IRenderable>(), second);
Если "first" объявлено как тип IRenderable.
Я думаю, вы действительно пытаетесь конвертировать из 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();
В качестве примера того, почему это не всегда безопасно (разрешенные варианты использования в C# 4 безопасны), рассмотрим следующий код:
List<Apple> apples = new List<Apple> { new Apple(...) };
List<Fruit> fruit = apples;
fruit.Add(new Orange());
Теперь список, который apples
относится к апельсину! Это явно нехорошо с точки зрения безопасности типов.
Как говорит Дрис, если вы можете дать больше информации (например, что у вас есть и чего вы хотите), мы сможем помочь вам больше.
List<T0>
не поддается List<T1>
, Вы должны сделать кастинг для каждого элемента списка. Расширение Cast для IEnumarable состоит в следующем:
List<IScreen> Screens = new List<IScreen>();
List<IRenderable> renderList = Screens.Cast<IRenderable>().ToList();