Какой синтаксис разрешен при применении атрибутов C #? - PullRequest
11 голосов
/ 19 января 2012

Это самые распространенные и единственные шаблоны, которые я видел до сих пор:

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

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

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

См. Также: Применение атрибутов в MSDN

Ответы [ 3 ]

8 голосов
/ 19 января 2012

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

[AttributeFoo, AttributeBar("Hello world!"), AttributeBaz(foo=42,bar="Hello world!")]
public class Example {}
4 голосов
/ 19 января 2012

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

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

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

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

Параметры атрибута ограничены постоянными значениями следующие типы:

  • Простые типы (bool, byte, char, short, int, long, float и double)
  • строка
  • System.Type
  • перечисления
  • объект (Аргумент к параметру атрибута объекта типа должен быть постоянным значением одного из вышеуказанных типов.) Одномерный массивы любого из вышеперечисленных типов

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

//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")})]

РЕДАКТИРОВАТЬ: просто для уточнения, атрибуты образуют часть метаданных для конструкций, к которым они применяются (в пределах сгенерированного IL), таким образом, члены класса атрибута должны быть определены во время компиляции; отсюда ограничение на параметры атрибута постоянными значениями.

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...