方法组自然类型改进

注意

本文是特性规范。 该规范充当该功能的设计文档。 它包括建议的规范更改,以及功能设计和开发过程中所需的信息。 这些文章将发布,直到建议的规范更改最终确定并合并到当前的 ECMA 规范中。

功能规范与已完成的实现之间可能存在一些差异。 这些差异记录在相关的 语言设计会议(LDM)笔记中。

可以在 规范一文中详细了解将功能规范采用 C# 语言标准的过程。

支持者问题:https://github.com/dotnet/csharplang/issues/7429

总结

此建议通过多种方式优化方法组的自然类型的确定:

  1. 逐个范围考虑候选方法(首先是实例方法,然后是每个范围内的扩展方法)
  2. 修剪那些没有成功机会的候选项,这样他们就不会干扰确定唯一的签名:
    • 如果未提供类型参数(var x = M;),则删除泛型实例方法
    • 根据可减少扩展的能力和约束条件来修剪泛型扩展方法

方法组自然类型的上下文

在 C# 10 中,方法组获得了弱的自然类型。
该类型是一种“弱类型”,因为它仅在方法组不是目标类型(即它在 System.Action a = MethodGroup;中没有作用)时才起作用。
这种弱自然类型可能出现 var x = MethodGroup; 等情况。

作为参考:https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/lambda-improvements.md#natural-function-type

如果方法组中的所有候选方法都具有通用签名,则方法组具有自然类型。 (如果方法组可能包含扩展方法,则候选项包括包含类型和所有扩展方法范围。

在实践中,这意味着我们:

  1. 构造所有候选方法集:
  • 相关类型的方法位于集中(如果它们是静态的,并且接收方是一种类型,或者它们是非静态的,并且接收方是值)
  • 可以缩减的扩展方法(在所有范围内)属于该集合。
  1. 如果所有候选项的签名不匹配,则方法组没有自然类型
  2. 如果生成的签名的 arity 与所提供的类型参数的数目不匹配,则方法组没有自然类型
  3. 否则,生成的签名将用作自然类型

建议

原则是逐个范围地仔细筛选候选对象,尽早去除那些我们已知不可能成功的候选者,这就是重载解析中使用的相同原则。

  1. 对于每个范围,我们将构造一组所有候选方法:
  • 对于初始范围,如果相关类型的方法是静态的,并且接收者是类型;或者如果它们是非静态的,并且接收者是值,则这些方法与提供的类型参数基本匹配,并且使用提供的类型参数满足约束,则这些方法都在集合中
  • 对于后续作用域,该作用域中的扩展方法可以用提供的类型参数替换,并在满足约束条件的同时使用接收器的值进行缩减
  1. 如果在给定范围内没有候选项,请转到下一个范围。
  2. 如果所有候选项的签名不匹配,则方法组没有自然类型
  3. 否则,生成的签名将用作自然类型
  4. 如果范围已用尽,则方法组没有自然类型

与逐范围建议相关:https://github.com/dotnet/csharplang/issues/7364 与更好地处理通用扩展方法的建议相关:https://github.com/dotnet/roslyn/issues/69222