为什么属性成员需要public?

Why do Attribute members need to be public?

问题

正在尝试使用属性

internal class FooAttribute : Attribute
{
    internal string Bar { get; set; }
}

像这样

[Foo(Bar = "hello world")]
public class MyOtherClass { }

(在同一个程序集中)产生

error CS0617: 'Bar' is not a valid named attribute argument. Named attribute arguments must be fields which are not readonly, static, or const, or read-write properties which are public and not static.

但是,我可以完美地从 "in code" 访问 Bar,例如

FooAttribute attribute = new FooAttribute { Bar = "hello world" };

解决方案

但是,如果我将属性更改为

internal class FooAttribute : Attribute
{
    public string Bar { get; set; }
    ^^^^^^
}

我可以按预期使用它。 请注意,我只需要标记 属性 public - 而不是属性本身。尽管 有效地 没有改变 Bar.

的可见性,但这“解决了”问题

为什么在这种情况下属性是“特殊的”——为什么编译器要求它们的字段是 public?

documentation on the error也没有提到为什么他们也需要public。

Why are attributes "special" in this case

您将错误的部分识别为特殊的。属性的特殊之处在于,对于与字段、classes、方法等关联的对象,public 属性有一种构造和设置组合的语法

换句话说,属性的特殊之处在于它们是属性!

事实上,它甚至不是特殊的属性;正如您自己所说,您可以使用与任何其他初始化程序相同的初始化程序创建相同 class 的实例。这是特殊的属性语法。

它必须允许调用 public 构造函数(否则永远不可能构造)并且它必须允许设置 public 属性(否则永远不会设置属性) .还值得注意的是,这早于将初始化语法引入 C# 之前,因此曾几何时,在属性的情况下,只能将 public 属性的构造和立即设置组合在一个语法单元中。

如此考虑,与初始化器的工作方式相比毫无意义,因为在做出相关设计决策时它们并不存在。

所以,让我们单独考虑 [Foo(Bar = "hello world")],并考虑什么时候可以这样设置 Bar

Bar 为 public 时允许它的原因应该很明显。 当 Bar 是私有的时不允许它的原因也应该很明显。 当其内部有两个合理的选择时;当属性存在于给定程序集中时不允许或允许。

所以问题是拥有一个 public 的属性有多大用处(如果它本身是内部的,我们可以用所有 -public 属性实现同样的事情)因此可以在其他程序集中使用,但具有只能在同一程序集中使用的属性中设置的内部属性。如果这是超级有用的,那么允许它的额外工作和复杂性将是值得的。如果它不是超级有用,那么理论(规范)和实践(编译器)都最好不要允许它。

它似乎没有被认为是超级有用的。