Почему свойства атрибутов должны быть доступны для чтения?

Рассмотрим следующий атрибут.

internal class NiceAttribute : Attribute
{
  private string _stuff;

  public string Stuff
  {
    set { _stuff = value; }
  }
}

Когда я пытаюсь использовать атрибут [Nice(Stuff = "test")], компилятор выдает следующую ошибку.

'Stuff' не является допустимым аргументом атрибута name. Именованный атрибут аргументы должны быть полями, которые не являются readonly, static или const, или read-write, которые являются общедоступными, а не статическими.

Какова рациональность требования к тому, чтобы свойство было удобочитаемым?


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

interface ISettingsBuilder
{
  Settings GetSettings();
}

class SettingsAttribute : Attribute, ISettingsBuilder
{
  private readonly IDictionary<string, object> _settings =
    new Dictionary<string, object>();

  public Settings GetSettings()
  {
    // Use _settings to create an immutable instance of Settings
  }

  public string Stuff
  {
    set { _settings["Stuff"] = value; }
  }

  // More properties ...
}

Могут быть другие реализации ISettingsBuilder. Например, тот, который предлагает хороший API для создания настроек с помощью кода.

Я закончил с внедрением своих геттеров, выбросив NotImplementedException.

  public string Stuff
  {
    get { throw new NotImplementedException(); }
    set { _settings["Stuff"] = value; }
  }

Можете ли вы придумать более удобный способ сделать что-то подобное?

Ответы

Ответ 1

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

Изменить "мы" теперь располагаем фактическим источником. В информационных целях здесь приводится полная разбивка, но не стесняйтесь проскальзывать донизу.
(обратите внимание, как ошибка должна быть подана против компилятора Mono. Я подумаю, что на какое-то время)

Ошибка компилятора CS0617

'reference' не является допустимым аргументом атрибута named. Именованные атрибуты атрибута должны быть полями, которые не являются readonly, static или const или свойствами чтения и записи, которые не являются статическими.

Была предпринята попытка доступа к частному члену класса атрибутов.

Может показаться, что он использует какой-то поиск (похожий на отражение), чтобы убедиться, что getter доступен, и если это не так, сделайте вывод, что он должен быть закрытым.

Это, конечно, не обязательно:)

Моно совместимость:

Для развлечения заметим, что монокомпилятор не имеет никаких проблем, принимая этот атрибут: https://ideone.com/45fCX

Из-за Reflection:

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

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

Update @Arun разместил соответствующую цитату, которая подтверждает эту гипотезу (спасибо!):

<суб >

Доступ к атрибутам через отражение После того, как атрибуты были связаны с элементами программы, отражение может использоваться для запроса их существования и значений. Основные методы отражения атрибутов запроса содержатся в классе System.Reflection.MemberInfo(семейство методов GetCustomAttributes).   Суб >

Итак, причина должна быть: Параметры атрибута должны иметь отражаемые значения

Вопрос о премии: как это работает с позиционными параметрами? Как бы это отразилось на них?

Ответ 2

Эта ссылка является ссылкой из Visual Studio 2003, но я думаю, это вряд ли изменилось.

Соответствующая часть из этой ссылки:

Доступ к атрибутам через отражение Когда атрибуты связаны с элементами программы, отражение может использоваться для запроса их существования и значений. Основные методы отражения атрибутов запроса содержатся в классе System.Reflection.MemberInfo(семейство методов GetCustomAttributes).