Как назвать класс, который использует атрибут? - PullRequest
1 голос
/ 28 января 2012

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

public class FooAssignableAttribute : Attribute  
{ 
    ... 
} 

[FooAssignable] 
public class Foo  
{     
   ... 
} 

Разве я не могу написать такой словарь?

Dictionary<string, FooAssignable> dictionary;

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

Ответы [ 4 ]

2 голосов
/ 28 января 2012

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

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

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

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

1 голос
/ 28 января 2012

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

public class FooAssignable : Attribute
{ ... }
1 голос
/ 28 января 2012

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

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

0 голосов
/ 28 января 2012

Будьте последовательны с вашим собственным руководством по стилю или выберите любое существующее руководство по стилю.

...