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

本文关键字:属性 为什么 | 更新日期: 2023-09-27 18:10:01

考虑以下属性:

internal class NiceAttribute : Attribute
{
  private string _stuff;
  public string Stuff
  {
    set { _stuff = value; }
  }
}

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

'Stuff'不是一个有效的命名属性参数。命名属性参数必须是非只读、静态或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来实现我的getter。

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

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

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

我怀疑编译器正在使用稍微错误的检查来查看您是否正在访问私有属性

编辑"我们"现在已经找到了实际的来源。出于信息目的,这里是完整的细分,但可以随意跳到底部。
(注意应该如何向Mono编译器提交bug。我再考虑一会儿)

编译错误CS0617

  • http://msdn.microsoft.com/en-us/library/978b3z1b (v = vs.71) . aspx

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

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

似乎正在使用某种查找(类似于反射)来确保getter可访问的,如果不是,则断定它必须是私有的

当然,它不需要是:)

Mono兼容性:

有趣的是,观察mono编译器接受这个属性没有任何问题:https://ideone.com/45fCX

Because of Reflection:

当然,也可能是编译器要求属性参数具有可反射的值。如果属性不是公共可读的,你只能使用反射来"观察"属性的存在,而不能使用初始化的参数。

我不知道为什么会做出这样的设计选择,但是如果考虑到反射的使用,它确实是有意义的。

更新 @Arun发布了证实这一猜想的相关报价(谢谢!):

<子>

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

所以原因一定是:属性参数必须有可反射的值

关键问题:如何处理位置参数?如何反映这些呢?

这个链接是来自Visual Studio 2003的参考,但我想它几乎没有改变。

链接的相关部分:

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