为什么属性成员需要公开?

时间:2018-07-05 15:16:18

标签: c# attributes visibility

问题

尝试使用属性

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并没有提及为什么它们也必须公开。

1 个答案:

答案 0 :(得分:1)

  

在这种情况下,为什么属性是“特殊的”

您将错误的部分识别为特殊部分。关于属性的特殊之处在于,存在一种与字段,类,方法等关联的对象的公共属性的构造和设置相结合的语法。

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

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

它必须具有调用公共构造函数的能力(否则将永远不可能进行构造),并且必须允许设置公共属性(或永远不会设置属性)。还值得注意的是,这早于在C#中引入初始化程序语法,因此从前,在属性的情况下,只能将构造和公共属性的立即设置组合在一个语法单元中。

因此,考虑到这一点,没有必要与初始化程序的工作方式进行比较,因为在制定相关的设计决策时就不存在初始化程序。

因此,我们仅考虑[Foo(Bar = "hello world")],并考虑何时应该以这种方式设置Bar

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

那么问题是,拥有一个公共属性(如果它本身是内部属性,我们可以使用全公共属性实现相同的事情)并因此可以在其他程序集中使用但具有内部属性又有多大用处?只能在同一程序集中的属性使用中设置。如果这样做非常有用,那么值得额外的工作和复杂性。如果不是超级有用,那么从理论(规范)到实践(编译器)的角度都不允许这样做。

似乎没有用处。