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

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

public class FooAssignableAttribute : Attribute  
{ 
    ... 
} 

[FooAssignable] 
public class Foo  
{     
   ... 
} 

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

Dictionary<string, FooAssignable> dictionary;

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

4 ответа

Решение

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

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

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

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

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

public class FooAssignable : Attribute
{ ... }

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

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

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

Другие вопросы по тегам