尝试使用属性
internal class FooAttribute : Attribute
{
internal string Bar { get; set; }
}
像这样
[Foo(Bar = "hello world")]
public class MyOtherClass { }
(在同一程序集中)产生
错误CS0617:“ Bar”不是有效的命名属性参数。命名属性参数必须是非只读,静态或const字段,或者是公共且非静态的读写属性。
但是,我可以完美地从“以代码形式” (例如
)访问Bar
FooAttribute attribute = new FooAttribute { Bar = "hello world" };
但是,如果我将属性更改为
internal class FooAttribute : Attribute
{
public string Bar { get; set; }
^^^^^^
}
我可以按预期使用它。
请注意,我只需要标记属性public
,而不必标记属性本身。尽管有效地并没有改变Bar
的可见性,但这仍“解决了”问题。
在这种情况下,为什么属性是“特殊的”-为什么编译器要求其字段公开?
documentation on the error并没有提及为什么它们也必须公开。
答案 0 :(得分:1)
在这种情况下,为什么属性是“特殊的”
您将错误的部分识别为特殊部分。关于属性的特殊之处在于,存在一种与字段,类,方法等关联的对象的公共属性的构造和设置相结合的语法。
换句话说,关于属性的特殊之处在于它们是属性!
实际上,甚至不是特殊的属性;正如您自己说的那样,您可以使用与其他任何对象相同的初始化程序创建相同类的实例。这是特殊的属性语法。
它必须具有调用公共构造函数的能力(否则将永远不可能进行构造),并且必须允许设置公共属性(或永远不会设置属性)。还值得注意的是,这早于在C#中引入初始化程序语法,因此从前,在属性的情况下,只能将构造和公共属性的立即设置组合在一个语法单元中。
因此,考虑到这一点,没有必要与初始化程序的工作方式进行比较,因为在制定相关的设计决策时就不存在初始化程序。
因此,我们仅考虑[Foo(Bar = "hello world")]
,并考虑何时应该以这种方式设置Bar
。
在Bar
公开时允许它的原因应该很明显。
当Bar
为私有时不允许使用它的原因也应该很明显。
当其内部有两个合理的选择;不允许或不允许该属性存在于给定程序集中。
那么问题是,拥有一个公共属性(如果它本身是内部属性,我们可以使用全公共属性实现相同的事情)并因此可以在其他程序集中使用但具有内部属性又有多大用处?只能在同一程序集中的属性使用中设置。如果这样做非常有用,那么值得额外的工作和复杂性。如果不是超级有用,那么从理论(规范)到实践(编译器)的角度都不允许这样做。
似乎没有用处。