为什么属性的属性必须是可读的?

时间:2011-09-29 22:31:13

标签: c# attributes properties compiler-errors

考虑以下属性。

internal class NiceAttribute : Attribute
{
  private string _stuff;

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

当我尝试使用属性[Nice(Stuff = "test")]时,编译器会出现以下错误。

  

'Stuff'不是有效的命名属性参数。命名属性   参数必须是非readonly,static或const的字段,或者   读写属性,这些属性是公开的而非静态的。

要求该属性可读的理由是什么?


更新
我将尝试绘制我的用例,以便在属性上具有只写属性。

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; }
  }

你能想出一个更好的方法来做这样的事吗?

2 个答案:

答案 0 :(得分:7)

我怀疑编译器使用了一个稍微误导的检查,看你是否在这里访问一个私有财产

编辑“我们”现在找到了实际来源。出于提供信息的目的,这里有完整的细分,但请随时跳到底部。
(注意应该如何针对Mono编译器提交bug。我认为这个问题会持续一段时间)

编译器错误CS0617

  

'reference'不是有效的命名属性参数。命名属性参数必须是非readonly,static或const的字段,或者不是静态的读写属性。

     

尝试访问属性类的私有成员。

似乎它正在使用某种查找(类似于反射)来确保 getter 可访问并且如果结论是必须是私有的

当然,这不一定是:)

单声道兼容性:

为了好玩,请注意单声道编译器在接受此属性时没有任何问题:https://ideone.com/45fCX

因为反思:

当然可能是编译器要求属性参数具有可反映的值。如果属性不是公开可读的,则只能使用反射来“观察”属性存在,而不是使用它初始化的参数。

我不确切地知道为什么这样的设计选择,但如果考虑到反射的使用,它确实有意义。 < /子>

更新 @Arun发布了确认此推测的相关引文(谢谢!):

<子>

  
    

通过反射访问属性一旦属性与程序元素相关联,就可以使用反射来查询它们的存在和值。查询属性的主要反射方法包含在System.Reflection.MemberInfo类(GetCustomAttributes方法系列)中。     

  

原因必须是: 属性参数必须具有可反映的值

奖项问题:这与位置参数有什么关系?如何反映这些?

答案 1 :(得分:3)

This link是来自Visual Studio 2003的引用,但我想它几乎没有改变。

该链接的相关部分:

  

通过反思访问属性   一旦属性与程序元素相关联,就可以使用反射来查询它们的存在和值。查询属性的主要反射方法包含在System.Reflection.MemberInfo类(GetCustomAttributes方法系列)中。