объединение других ответов в простейшую форму ... аннотация с простым списком значений ...
@Foos ({"one", "two"}) private String AWK; // ... public @interface Foos {String [] value (); }
Причина, по которой вы не можете сделать это, состоит в том, что список доступен для записи. Предположим, что это было законным, и посмотрите, что пойдет не так:
List & lt; Cat & gt; cats = new List & lt; Cat & gt; (); Список & л; Животное & GT; животные = кошки; // Проблемы пивоварения ... animals.Add (новая собака ()); // эй, мы просто добавили собаку в список кошек ... кошек [0] .Speak (); // Уоф!
Хорошо, собака, мои кошки, это нехорошо.
Функция, которую вы хотите, называется «общей ковариацией», и она поддерживается в C # 4 для интерфейсов, которые, как известно, являются безопасными. IEnumerable & lt; T & gt;
не имеет никакого способа записи в последовательность, поэтому он безопасен.
класс Animal {public virtual void Play (IEnumerable & lt; Animal & gt; животные ) {}} class Cat: Animal {public override void Play (IEnumerable & lt; Animal & gt; животные) {}} class Program {static void Main () {Cat cat = new Cat (); cat.Play (новый список & lt; Cat & gt; ()); }}
Это будет работать в C # 4, потому что List & lt; Cat & gt;
конвертируется в IEnumerable & lt; Cat & gt;
, который можно конвертировать в IEnumerable & л; & животные триазоли
. Нельзя использовать Play IEnumerable & lt; Animal & gt;
, чтобы добавить собаку к тому, что на самом деле является списком кошек.
Вы могли бы сделать несколько вещей. Один из примеров - это элементы в списке Animal
Используя ваш код:
cat.Play ( новый список & lt; Cat & gt; (). Cast & lt; Animal & gt; (). ToList ());
Другим является создание Animal
generic, поэтому cat.Play (новый List & lt; Cat & gt; ());
будет работать. [ ! d13]
класс Animal & lt; T & gt; {public virtual void Play (List & lt; T & gt; животные) {}} класс Cat: Animal & lt; Cat & gt; {public override void Play (List & lt; Cat & gt; cats) {}} class Program {static void Main (string [] args) {Cat cat = new Cat (); cat.Play (новый список & lt; Cat & gt; ()); }}
Другим способом является не создание Animal
generic, а метод Play
и ограничение этого на T: Animal
класс Animal {public virtual void Play & lt; T & gt; (List & lt; T & gt; животные), где T: Animal {}} класс Cat: Animal {public override void Play & lt; T & gt; (List & lt; T & gt; животные) {}}
Наконец, если вы находитесь на C # 4 и вам нужно только перечислить список и не изменять его, проверьте ответ Эрика Липперта на IEnumerable & л; Животное & GT;!.! [D9] [D15]
использовать метод расширения Cast ()
so:
class Program {static void Main (string [] args) {Cat cat = new Cat (); cat.Play (новый список & lt; Cat & gt; (). Cast & lt; Animal & gt; ()); }}
Причиной этого является b / c .net 3.5 не поддерживает ковариацию, но 4.0 делает:)
cat.Play (новый список & lt; Cat & gt; ());
также не будет работать в 4 с существующим кодом.
– Anthony Pegram
15 September 2010 в 20:05
Вы ищете общую ковариацию коллекции. Очевидно, что эта функция не поддерживается версией C #, которую вы используете.
Вы можете обойти это, используя метод расширения Cast & lt; gt; ()
, Имейте в виду, что это создаст копию исходного списка вместо передачи оригинала как другой тип:
cat.Play ((новый список & lt; Cat & gt; ()). ; Животное & GT; () ToList ()).
List & lt; Animal & gt; list = new List & lt; Dog & gt; ();
Следующее приведет к сбою приложения: list.Add (новый Elephant ());
.
– Dykam
15 September 2010 в 21:54
Все упоминают метод литья уже. Если вы не можете обновить до 4.0, способ скрыть листинг
class Cat: Animal {public override void Play (List & lt; Animal & gt; animal) {Play ((List & lt; Cat & gt;) animal ); } public virtual void Play (List & lt; Cat & gt; animal) {}}
Это тот же трюк IEnumable
и IEnumarable & lt; T & gt;
играть за GetEnumerator