扩展的
注意
本文是一篇特性规范。 此规范是功能的设计文档。 它包括建议的规范变更,以及功能设计和开发过程中所需的信息。 这些文章将持续发布,直至建议的规范变更最终确定并纳入当前的 ECMA 规范。
功能规范与已完成的实现之间可能存在一些差异。 这些差异记录在相关的 语言设计会议(LDM)笔记中。
可以在有关规范的文章中了解更多有关将功能规范子块纳入 C# 语言标准的过程。
支持者问题:https://github.com/dotnet/csharplang/issues/373
总结
允许在方法或参数的属性中使用 nameof(parameter)
。
例如:
[MyAttribute(nameof(parameter))] void M(int parameter) { }
[MyAttribute(nameof(TParameter))] void M<TParameter>() { }
void M(int parameter, [MyAttribute(nameof(parameter))] int other) { }
动机
NotNullWhen
或 CallerExpression
等属性需要引用参数,但这些参数当前不在范围内。
详细设计
该方法的 type_parameters 在整个 method_declaration 的范围内,可用于在 return_type、method_body 和 type_parameter_constraints_clauses 中形成整个范围的类型,但不在 attributes 中,除非在 attributes 中的 nameof
表达式中。
方法声明为参数、类型参数和局部变量创建单独的声明空间。 名称由方法的类型参数列表、形式参数列表以及方法块中的局部变量声明引入此声明空间。
名称是通过方法或其参数上的属性中的 nameof
表达式中的类型参数列表和方法的形式参数列表引入此声明空间的。
[...]
在方法的块中,形式参数可以通过 simple_name 表达式(简单名称)中的标识符引用。
在放置在方法或其参数上的属性中的 nameof
表达式中,形式参数可以通过 simple_name 表达式中的标识符引用。
匿名函数的参数范围是放置在匿名函数或其参数 nameof
和 表达式。
委托的参数范围是放置在声明上的属性中的 nameof
表达式、其类型参数或其参数。
simple_name 的形式可以是 I
或 I<A1,...,Ak>
,其中 I
是一个单个标识符,<A1,...,Ak>
是可选 type_argument_list。 如果未指定任何 type_argument_list,请将 K
视为零。 simple_name 的计算和分类如下:
- 如果
K
为零,并且 simple_name 出现在块内,并且块(或封闭块)的局部变量声明空间 (Declarations) 包含一个名为I
的局部变量、参数或常量,则simple_name 引用该局部变量、参数或常量,并被分类为变量或值。 - 如果
K
为零,并且 simple_name 出现在泛型方法声明的正文中,并且如果该声明包含名称为I
的类型参数,则 simple_name 将指向该类型参数。 - 如果
K
为零,并且 simple_name 出现在方法声明或其参数的属性中的nameof
表达式中,如果该声明包含名称I
的参数或类型参数,则 simple_name 引用该参数或类型参数。 - 否则,对于每个实例类型
T
(实例类型),从紧接着的封闭类型声明的实例类型开始,然后从每个封闭类或结构声明的实例类型开始(如果有的话):
[...] - 否则,对于每个命名空间
N
,从 simple_name 所在的命名空间开始,继续每个封闭的命名空间(如果有),直到全局命名空间,以下步骤将被执行,直到找到一个实体:
[...] - 否则,simple_name 未定义,且发生编译时错误。
- 由 type_parameter_list 在 method_declaration 上声明的类型参数的范围包括在方法声明或其参数的属性中的 和
nameof
表达式。 - method_declaration(方法)中声明的参数的范围是该方法声明或其参数的属性中的method_declaration 和
nameof
表达式的 method_body。