让有一堂课
class Class
{
}
和属性
class SomePropertyAttribute : Attribute
{
public SomePropertyAttribute(string prop)
{
}
}
为什么编译器在将属性应用于这样的类时不会抛出错误
[SomeProperty(Weird)] //<-- Weird const use
class Class
{
private const string Weird = nameof(Weird);
}
?
实际上,在这种情况下,在定义类的花括号之外使用了一个私有常量。而文档(见私人)说:
private关键字是成员访问修饰符。
...
私有成员只能 在声明它们的类或结构的主体内访问...
奇怪的是,您的示例与语言规范并不矛盾。
我自己无法找到并正确解释标准中的必要引用,但编译器的 github 存储库中的一个类似问题帮助了我。事实证明,类属性的名称解析发生在类本身的上下文中。因此,顺便说一下,您可以将常量称为
Weird而不是Class.Weird. 可见性规则的“违反”在这里不会发生,该属性实际上位于类内部。让我们在规范中找到对此的确认。在名称解析阶段,
Weird它被归类为“简单名称”,其绑定受规范第 7.6.2 节的约束。相关部分:抒情官僚题外话。
这部分适合我们吗?该属性是否存在于任何类型声明中(立即包含类型声明)?它看起来像在外面,但事实并非如此。根据第 10.1 节,类声明是类型声明
并包括一个属性声明:
我们回到主题。我们有
T一个类型Class。该规范包含以下子条款:这部分是合适的,因为它
Weird是类的成员常量(通过滚动成员查找部分可以看到)。因此,在这种情况下,它
Weird解析为 type 的一部分Class。C# 中的属性将元数据添加到程序集。更准确地说,在我们班上。
在这种情况下,属性和常量的范围在编译级别是相同的。因此,您的示例有效。