2012-01-18 2 views
8

Они являются наиболее распространенными и только модели, которые я видел до сих пор:Какой синтаксис разрешен при применении атрибутов C#?

[AttributeFoo] 
[AttributeBar("Hello world!")] 
[AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 

синтаксис атрибута выглядит как вы вызываете конструктор. И до того, как C# поддерживал необязательные и именованные аргументы, имена параметров для атрибутов были единственной видимой разницей.

Предоставляет ли компилятор C# что-нибудь еще? Как params аргументы или инициализаторы объектов/коллекций?

Смотрите также: Applying Attributes на MSDN

+0

Я как-то поместил инициализатор 'string []' в атрибут. – JohnL

ответ

3

AFAIK, названные параметры допускают только интегральные типы. К сожалению, у меня нет ссылки на это, я только узнал об этом благодаря своим собственным экспериментам.

При попытке использовать объект инициализаторы, я получил эту ошибку от компилятора:

Аргумент атрибута должен быть константным выражением, TypeOf выражения выражения или создания массива ссылочного типа параметра атрибута

Хотя это documentation составляет несколько лет, он имеет справочную информацию, которую я искал:

Attribute р arameters ограничены постоянных значения следующих типов:

  • Простых типы (BOOL, байты, символ, короткая, INT, длинная, с плавающей точкой и двойная)
  • струнного
  • System.Type
  • enums
  • объект (Аргумент параметра атрибута объекта типа должен быть постоянным значением одного из вышеуказанных типов.) Одномерные массивы любого из перечисленных выше типов

Так это работает:

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public int[] Something { get; set; } 
} 

//Using an array initialiser - an array of integers 
[TestAttribute(Something = new int[]{1, 2, 3, 4, 5})] 
public abstract class Something 

В то время как это не так:

//Test person class 
internal class Person 
{ 
    public string Name { get; set; } 

    public Person(string name) 
    { 
     this.Name = name; 
    } 
} 

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public IEnumerable<Person> Something { get; set; } 
} 

//This won't work as Person is not an integral type 
[TestAttribute(Something = new Person[]{new Person("James")})] 

EDIT: только для разработки, атрибуты составляют часть метаданных для конструкций, к которым они применяются (внутри сгенерированного ИЛ), поэтому члены класса атрибута должны быть определены во время компиляции; следовательно, ограничение по параметрам атрибута на постоянные значения.

0

Позиционные параметры необходимы и должны перед любыми именованными параметрами; они соответствуют параметрам одного из конструкторов атрибута. Именованные параметры являются необязательными и соответствуют свойствам чтения/записи атрибута. В C++, C# и J # укажите имя = значение для каждого необязательного параметра, где name - это имя свойства. В Visual Basic укажите имя: = значение.

Из указанной ссылки. Похоже, что это единственное, что разрешено. В основном вы комбинируете конструктор со встроенной логикой инициализации свойств, как вы упомянули.

3

В дополнение к тому, что говорили другие, я хотел бы указать, что атрибуты также могут быть разделены запятой.

[AttributeFoo, AttributeBar("Hello world!"), AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 
+2

Это плохая практика; это менее читаемо. – Jowen