С# attribute-target-specifier
Забавно, не смотря на то, что грамматика C# для указания аннотируемого атрибутом элемента языка, предусматривает ограниченный набор значений:
attribute-section:
[ attribute-target-specifieropt attribute-list ]
[ attribute-target-specifieropt attribute-list , ]
attribute-target-specifier:
attribute-target :
attribute-target:
field
event
method
param
property
return
type
На деле (компилятор С# 4.0) всё оказывается несколько иначе, код:
[someCrazyAttributeTargetLocation: Serializable]
class Foo { }
Компилируется без ошибок, но с одним warning’ом:
warning CS0658: ‘someCrazyAttributeTargetLocation’ is not a recognized attribute location. All attributes in this block will be ignored.
Соответственно, в рантайме получаем typeof(Foo).IsSerializable == false
. Однако, читая Владимира Решетникова на rsdn, можно обнаружить, что существует ещё один attribute-target-specifier, не перечисленный в грамматике C#, который компилятор воспринимает без warning’а:
[AttributeUsage(AttributeTargets.GenericParameter)]
sealed class FooAttribute : Attribute { }
sealed class Bar<[typevar: Foo] T> { }
Знакомьтесь, скрытый attribute-target-specifier - typevar
. Применение атрибута где-либо вне типа-параметра (если убрать [AttributeUsage]
) будет результировать предупреждением CS0658.
Компилятор F# более строг и использование произвольных attribute-target не позволяет вовсе.