2012-01-27 2 views
1

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

public class FooAssignableAttribute : Attribute 
{ 
    ... 
} 

[FooAssignable] 
public class Foo 
{  
    ... 
} 

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

Dictionary<string, FooAssignable> dictionary; 

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

+0

Вы не можете этого сделать. Атрибуты не являются частью системы типов C#, и это не является ограничением, которое вы можете сделать. Почему вам нужно выразить это ограничение на основе атрибутов? – millimoose

+0

И? поэтому вы этого не хотите, но это то, что нужно сделать ... в чем вопрос? –

+0

Я отформатировал ваши образцы кода для вас. Для дальнейшего использования в образцах кода необходимо отформатировать четыре пробела для правильной отображения (или вы можете использовать кнопку '{}' над полем редактирования). –

ответ

2

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

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

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

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

+0

У меня не было представления об этом. Но можете ли вы объяснить мне больше о последнем предложении? –

+0

Как я понимаю, вам нужен словарь, который отображает строки в объекты, имеющие атрибут FooAssignable. Это невозможно, поскольку FooAssignableAttribute как тип относится только к самому атрибуту - это не означает «объекты с атрибутом FooAssignable». Но если вы создадите интерфейс маркера, IFooAssignable и сделаете все, что вы поместили в свой FooAssignableAttribute, чтобы реализовать его, вы можете сделать словарь из строки в IFooAssignable. IFooAssignable - это тип, который может использоваться вашими полезными объектами. Для общей коллекции требуется «is a», но отношение к атрибуту «имеет». –

+0

+1 Похоже, вы поняли его с тех пор, как переключали OP ответы. – LarsTech

1

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

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

1

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

public class FooAssignable : Attribute 
{ ... } 
+0

Это не проблема. Darf Zon хочет коллекцию (объекты, помеченные FooAssignable), а не набор (объекты типа FooAssignable), что и будет реализовано. Это проблема с областью, и без единого суперкласса, который реализует FooAssignable, нет никакого способа сделать это без интерфейса. –

+0

@AdamNorberg Когда я ответил, Джо Уайт почти покрыл это, подумал я.Если вы посмотрите историю изменений вопроса, изначально она пыталась использовать имя класса без расширения «attribute» в конце ключевого слова, например, как имя атрибута украшает класс. Насколько я знаю, нет правила, согласно которому атрибуты «должны» заканчиваться именем «Attribute», прикрепленным к ним. Просто давая ОП другой вариант, так как он не хотел, чтобы действительно длинное имя. – LarsTech

+0

Вопрос был переписан на половину моего ответа. Я предположил, что жалоба касается не длины имени, а того, что это не объекты FooAssignableAttribute, которые должны были быть собраны, и вместо этого должны быть «объектами объекта, которые помечены с помощью FooAssignableAttribute», который сам не является тип. Я, кажется, прочитал это неправильно, однако, основываясь на принятии вашего ответа! –

0

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

+0

Это не проблема стиля - это принципиально для системы типов C#, и связанные атрибуты не являются типами. Типы атрибутов существуют, но object-tagged-with-an-attribute не является назначаемым типом. –

Смежные вопросы