Список кастов из класса Derived в список базового classа

У меня есть два classа: базовый class (Animal) и class, полученный из него (Cat). Базовый class содержит один виртуальный метод Play, который принимает List как входной параметр. Что-то вроде этого

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication9 { class Animal { public virtual void Play(List animal) { } } class Cat : Animal { public override void Play(List animal) { } } class Program { static void Main(string[] args) { Cat cat = new Cat(); cat.Play(new List()); } } } 

Когда я скомпилирую вышеуказанную программу, я получаю следующую ошибку

     Ошибка 2 Аргумент 1: невозможно преобразовать из 'System.Collections.Generic.List' в 'System.Collections.Generic.List'

Нужно ли это сделать?

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

 List cats = new List(); List animals = cats; // Trouble brewing... animals.Add(new Dog()); // hey, we just added a dog to a list of cats... cats[0].Speak(); // Woof! 

Ну собака мои кошки, это нехорошо.

Функция, которую вы хотите, называется «общей ковариацией», и она поддерживается в C # 4 для интерфейсов, которые, как известно, безопасны. IEnumerable не имеет возможности записать последовательность, поэтому он безопасен.

 class Animal { public virtual void Play(IEnumerable animals) { } } class Cat : Animal { public override void Play(IEnumerable animals) { } } class Program { static void Main() { Cat cat = new Cat(); cat.Play(new List()); } } 

Это будет работать в C # 4, потому что List конвертируется в IEnumerable , который можно конвертировать в IEnumerable . Невозможно, чтобы Play мог использовать IEnumerable чтобы добавить собаку к тому, что на самом деле является списком кошек.

Вы могли бы сделать несколько вещей. Одним из примеров является листинг элементов списка для Animal

Использование вашего кода:

 cat.Play(new List().Cast().ToList()); 

Другой – сделать Animal generic, поэтому cat.Play(new List()); должно сработать.

 class Animal { public virtual void Play(List animals) { } } class Cat : Animal { public override void Play(List cats) { } } class Program { static void Main(string[] args) { Cat cat = new Cat(); cat.Play(new List()); } } 

Другим способом является не создание Animal generic, а метод Play и ограничение этого на T : Animal

 class Animal { public virtual void Play(List animals) where T : Animal { } } class Cat : Animal { public override void Play(List animals) { } } 

Наконец, если вы находитесь на C # 4 и вам нужно только перечислить список и не изменять его, проверьте ответ Эрика Липперта на IEnumerable .

Вы ищете общую ковариацию коллекции. Очевидно, что эта функция не поддерживается версией C #, которую вы используете.

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

 cat.Play((new List()).Cast().ToList()); 

используйте метод расширения Cast ()

так:

 class Program { static void Main(string[] args) { Cat cat = new Cat(); cat.Play(new List().Cast()); } } 

Причиной этого является b / c .net 3.5 не поддерживает ковариацию, но 4.0 делает 🙂

Все упоминают метод литья уже. Если вы не можете обновить до 4.0, способ скрыть приведение

 class Cat : Animal { public override void Play(List animal) { Play((List)animal); } public virtual void Play(List animal) { } } 

Это тот же трюк IEnumable и IEnumarable для GetEnumerator

  • Класс является сырым типом. Ссылки на общий тип Class должны быть параметризованы
  • IEnumerable и Recursion с возвратом доходности
  • Как заставить Java-метод возвращать общий список любого типа?
  • Как решить Operator '! =' Нельзя применить к операндам типа T и T
  • Как использовать List to List
  • Договор сравнения и компаратора относительно нулевого
  • Почему конструктор C # не может вывести тип?
  • Неопределенный контейнер для хранения типично типизированных объектов в Java
  • Статический общий class как словарь
  • Есть ли общее ограничение, которое я мог бы использовать для оператора +?
  • Получить общий тип java.util.List
  • Давайте будем гением компьютера.