C# Math.Max 类型处理

本文关键字:处理 类型 Max Math | 更新日期: 2023-09-27 18:36:26

我正在编写一段代码来防止 ushort 溢出/下溢。在此之前,我尝试:

ushort a = 0; //ushort.MinValue
a -= 1; //returns 65535 (ushort.MaxValue)

然后我编写真正的代码,我希望这"失败"(无法检测到下溢):

ushort oldValue, rate, delta;
ushort newValue = Math.Max(ushort.MinValue, oldValue - rate * delta);

有趣的是,一个错误(CS0266)阻止我构建它。虽然我希望 C# 将使用ushort Max(ushort, ushort)重载,但它使用的是int Max(int, int)重载,并且ushort值会自动转换为int。当然,当我显式投射结果以ushort这工作正常时。

这让我想到,C# 是否检测到可能发生下溢,所以它使用 int 为我进行比较?

C# Math.Max 类型处理

这是因为oldValue - rate * delta的结果是int类型。这是因为定义运算符 +、-、* 和/的"最小数据类型"是int 。所以byteushort等首先转换为int。然后,结果又是一个int.所以你需要显式投射到ushort.

或者,您可以使用Convert.ToUInt16,如果发生溢出,它将引发异常。

根据此 MSDN 页,使用 ushort s 的计算的结果类型为 int。所以你需要做的是投射计算的结果

oldValue - rate * delta

返回ushort

(ushort)(oldValue - rate * delta)

C# 将(ushort * ushort)提升为int,并将后续(ushort - int)操作的结果也作为int。最后,重载解析通过将第一个ushort参数提升到 int 来为Max(ushort, int)调用选取Math.Max(int, int)

现在你遇到的问题(除了所有未初始化的变量之外)是Max(int, int)的结果是一个int,它没有隐式转换为ushort

有关详细信息,您可以阅读规范的以下部分:

  • 7.3.6.2 二进制数字提升("否则,两个操作数都转换为 int 类型。
  • 6.1.2 隐式数值转换
  • 7.5.3 重载解析
小于

int数据类型的乘法会产生int结果。

因此oldValue - rate * delta会导致intMath.Max(short.MinValue, int)的最佳过载是:

Math.Max Method (Int32, Int32)

(因为ushort/short可以隐式扩大到int,无需转换)