放宽值班人员要求

注意

本文是特性规范。 此规范是功能的设计文档。 它包括建议的规范变更,以及功能设计和开发过程中所需的信息。 这些文章将持续发布,直至建议的规范变更最终确定并纳入当前的 ECMA 规范。

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

可以在有关规范的文章中了解更多有关将功能规范子块纳入 C# 语言标准的过程。

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

总结

移位运算符要求将会放宽,以便右操作数不再仅限于 int

动机

使用除 int以外的类型时,使用另一个计算的结果(例如基于 leading zero count进行移动)并不少见。 诸如 leading zero count 之类的自然类型与输入类型(TSelf)相同,因此在许多情况下,这要求在移动之前将该结果转换为 int,即使该结果已在范围内也是如此。

在库计划开放的泛型数学接口的上下文中,这可能会带来问题,因为这种类型不为人熟知,因此转换到 int 可能是不可能的,甚至可能没有确切定义。

详细设计

移位运算符

§12.11 应重新表述如下:

- When declaring an overloaded shift operator, the type of the first operand must always be the class or struct containing the operator declaration,
and the type of the second operand must always be int.
+ When declaring an overloaded shift operator, the type of the first operand must always be the class or struct containing the operator declaration.

换句话说,第一个操作数必须是包含操作符声明的类或结构,且这个限制依然存在。 已经取消了限制,即第二个操作数必须是 int

二元运算符

§14.10.3 应按如下所示重写:

-*  A binary `<<` or `>>` operator must take two parameters, the first of which must have type `T` or `T?` and the second of which must have type `int` or `int?`, and can return any type.
+*  A binary `<<` or `>>` operator must take two parameters, the first of which must have type `T` or `T?`, and can return any type.

也就是说,第一个参数必须是 TT? 的限制依然存在。 取消了第二个操作数必须是 intint? 的限制。

二元运算符重载解析

§11.4.5 处的第一个要点应重写为如下所示:

  • 确定由 XY 提供的候选用户定义运算符集,以用于操作 operator op(x,y)。 该集由 X提供的候选运算符的联合组成,除非运算符是一个 shift 运算符,Y提供的候选运算符,每个运算符都使用候选用户定义运算符的规则 §11.4.6确定。 如果 XY 是相同的类型,或者如果 XY 派生自通用基类型,则共享候选运算符仅在组合集中出现一次。

也就是说,对于移位运算符,候选运算符只是类型 X提供的运算符。

缺点

用户将能够定义不符合建议准则的运算符,例如在 C# 中实现 cout << "string"

替代方案

库中公开的泛型数学接口可以改为公开明确命名的方法。 这可能会使代码更难以读取/维护。

泛型数学接口可能要求进行int偏移,并执行相应的转换。 此转换可能会很昂贵,或者甚至可能无法实现,具体情况取决于所涉及的类型。

未解决的问题

是否担心关于如何保留第二个操作数限制为 int的“意图”?

设计会议

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md