Как назвать класс, который использует атрибут?

Я кодирую пользовательские атрибуты вместо интерфейсов маркеров

public class FooAssignableAttribute : Attribute  
{ 
    ... 
} 

[FooAssignable] 
public class Foo  
{     
   ... 
} 

Разве я не могу закодировать словарь, как это?

Dictionary<string, FooAssignable> dictionary;

Избегая интерфейсов маркеров, я пытаюсь использовать пользовательские атрибуты. Почему я не могу написать приведенный выше код?


person Darf Zon    schedule 27.01.2012    source источник
comment
Вы не можете этого сделать. Атрибуты не являются частью системы типов C#, и это не ограничение, которое вы можете сделать. Зачем вам нужно выражать это ограничение на основе атрибутов?   -  person millimoose    schedule 28.01.2012
comment
И? так не хочется, а вот что надо сделать... в чем вопрос?   -  person Chen Kinnrot    schedule 28.01.2012
comment
Я отформатировал для вас образцы кода. Для дальнейшего использования образцы кода должны иметь отступ в четыре пробела для правильного отображения (или вы можете использовать кнопку {} над полем редактирования).   -  person Joe White    schedule 28.01.2012


Ответы (4)


Нет, это не работает. Параметрические типы универсальной коллекции (или других универсальных) в C# должны быть объявляемыми типами, а атрибуты существуют только как метаданные.

У вас не может быть объекта типа FooAssignable. У вас может быть объект с атрибутом FooAssignable, но это не то же самое, что иметь его в качестве супертипа. FooAssignable не является классом или интерфейсом и не является допустимым спецификатором типа. FooAssignableAttribute есть, но это тип, который относится к самому атрибуту, а не к элементам, помеченным этим атрибутом.

Учтите, что в словаре тип вывода для индексатора — это указанный вами тип вывода. Но у вас не может быть переменной типа FooAssignable — у вас может быть переменная типа, помеченного тегом FooAssignable, но не существует единого базового класса, подходящего для всех этих типов. Поскольку это объявление типа является недопустимым, этот Dictionary будет иметь недопустимый, несуществующий тип в качестве возвращаемого типа для получателя из его индексатора, среди многих других мест. Проверка типа C# не может быть спонтанно заменена с помощью универсальных механизмов проверкой наличия атрибута.

Все, что вы хотите, чтобы система типов проверяла для вас, должно быть частью системы типов. Оценка атрибутов не определяет типы, поэтому система типов не может сделать это за вас; между тем, дженерики — это часть языка, которая наиболее непосредственно взаимодействует с системой типов. Вам придется фактически пройти через систему типов, чтобы выполнить подобную проверку, и это означает вместо этого продвигать FooAssignableAttribute к интерфейсу (IFooAssignable?).

person Adam Norberg    schedule 27.01.2012
comment
Я понятия не имел об этом. Но не могли бы вы объяснить мне больше о последнем предложении? - person Darf Zon; 28.01.2012
comment
Насколько я понимаю, вам нужен словарь, который сопоставляет строки объектам с атрибутом FooAssignable. Это невозможно, потому что FooAssignableAttribute как тип относится только к самому атрибуту, а не к объектам с атрибутом FooAssignable. Но если вы создадите интерфейс маркера, IFooAssignable, и реализуете все, что вы поместили в свой FooAssignableAttribute, вы можете создать словарь из строки в IFooAssignable. IFooAssignable — это тип, которым могут быть ваши используемые объекты. Универсальная коллекция требует a, но отношение к атрибуту имеет a. - person Adam Norberg; 30.01.2012
comment
+1 Похоже, вы его поняли, так как ОП поменял ответы. - person LarsTech; 31.01.2012

FooAssignableAttribute — это имя класса. Если вы хотите сослаться на класс в коде, вы должны использовать его имя.

Сокращенное обозначение "Attribute" в конце работает только тогда, когда вы используете его в качестве атрибута, как в примере [FooAssignable] выше. Когда вы используете его как класс — например, как объявление переменной или аргумент универсального типа — вы должны использовать его имя класса.

person Joe White    schedule 27.01.2012

Просто измените имя класса (если возможно):

public class FooAssignable : Attribute
{ ... }
person LarsTech    schedule 27.01.2012
comment
Это не решает проблему — Дарфу Зону нужна коллекция (объектов, помеченных FooAssignable), а не коллекция (объектов типа FooAssignable), что и будет реализовано. Это проблема области действия, и без единого суперкласса, реализующего FooAssignable, невозможно сделать это без интерфейса. - person Adam Norberg; 28.01.2012
comment
@AdamNorberg Когда я ответил, Джо Уайт в значительной степени покрыл это, я думал. Если вы посмотрите на историю изменений вопроса, то изначально речь шла о попытке использовать имя класса без расширения атрибута в конце ключевого слова, например, как имя атрибута украшает класс. Насколько мне известно, не существует правила, согласно которому атрибуты должны заканчиваться прикрепленным к ним атрибутом имени. Просто дал ОП еще один вариант, так как ему не нужно было очень длинное имя. - person LarsTech; 28.01.2012
comment
Вопрос был переписан на полпути к моему ответу на него. Я предполагал, что жалоба была не на длину имени, а на то, что должны собираться не объекты FooAssignableAttribute, а вместо этого должны быть объекты Object с тегом FooAssignableAttribute, который сам по себе не является типом . Однако я, кажется, неправильно прочитал это, основываясь на принятии вашего ответа! - person Adam Norberg; 28.01.2012

Следуйте своему собственному руководству по стилю или выберите любое существующее руководство по стилю.

person jviladrich    schedule 27.01.2012
comment
Это не проблема стиля — это основа системы типов C#, и связанные атрибуты не являются типами. Типы атрибутов существуют, но объекты, помеченные атрибутом, не являются назначаемым типом. - person Adam Norberg; 28.01.2012