Почему Вы должны? Атрибуты дают дополнительную информацию для отражения, но если Вы внешне знаете, какие свойства Вы хотите Вас, не нуждаются в них.
Вы могли сохранить метаданные внешне относительно легко в базе данных или файле ресурсов.
На первый взгляд кажется, что этот должен (как в пиве должен быть бесплатным) работать. Однако быстрая проверка здравомыслия показывает нам, почему это невозможно. Имейте в виду, что следующий код не будет компилироваться . Он предназначен для того, чтобы показать, почему это не разрешено, хотя он выглядит нормально до определенного момента.
public interface IFoo { }
public class Bar : IFoo { }
public class Zed : IFoo { }
//.....
List<IFoo> myList = new List<Bar>(); // makes sense so far
myList.Add(new Bar()); // OK, since Bar implements IFoo
myList.Add(new Zed()); // aaah! Now we see why.
//.....
myList
- это List
, то есть может принимать любой экземпляр IFoo
. Однако это противоречит тому факту, что он был создан как List
. Поскольку наличие List
означает, что я могу добавить новый экземпляр Zed
, мы не можем этого допустить, поскольку базовый список на самом деле List
, который может '
Причина в том, что C # не поддерживает ко- и контравариантность для универсальных шаблонов в C # 3.0 или более ранних версиях. Это реализовано в C # 4.0, поэтому вы сможете делать следующее:
IEnumerable<IFoo> foo = new List<Bar>();
Обратите внимание, что в C # 4.0 вы можете привести к IEnumerable
Это связано с При создании списка вы указали, что T является IFoo, поэтому вы не можете создать его как Bar, поскольку они относятся к разным типам, хотя Bar поддерживает IFoo.
Список является типом в этом случае, и это не вопрос наследования. Список
Надеюсь, что это поможет.
Поскольку список IFoo
может содержать также несколько Bar
, но список IFoo
s ] - это не то же самое, что список Bar
s.
Обратите внимание, что я использовал английский выше вместо C #. Хочу подчеркнуть, что это не серьезная проблема; вы просто запутались в деталях синтаксиса. Чтобы понять ответ, вам нужно выйти за пределы синтаксиса и подумать о том, что он на самом деле означает.
Список IFoo
s может содержать Bar
, потому что Bar
также является IFoo
. Здесь мы говорим об элементах списка. Список по-прежнему представляет собой список IFoo
s. Мы этого не изменили.
Итак, список, который вы назвали foo
, по-прежнему является списком IFoo
s (более педантично, foo
объявлен как List
) . Ничего другого и быть не может. В частности, его нельзя превратить в список Bar
s ( List
). Список Bar
- это совершенно другой объект, чем список IFoo
s.
Если у вас есть список типа List
, вы можете вызвать list.add (new Baz ());
предполагая, что Baz
реализует IFoo
. Однако вы не можете сделать это с помощью List
, поэтому вы не можете использовать List
везде, где можете использовать List
.
Однако, поскольку Bar
реализует IFoo
,
Если вам нужно преобразовать список в список базового класса или интерфейса, вы можете сделать это:
using System.Linq;
---
List<Bar> bar = new List<Bar>();
bar.add(new Bar());
List<IFoo> foo = bar.OfType<IFoo>().ToList<IFoo>();