C#Math.Max类型处理

时间:2012-06-06 14:20:15

标签: c# overflow type-conversion underflow

我正在编写一段代码来阻止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为我进行比较?

4 个答案:

答案 0 :(得分:2)

这是因为oldValue - rate * delta的结果属于int类型。这是因为定义了运算符+, - ,*和/的“最小数据类型”是int。因此byteushort等首先转换为int。然后,结果再次是int。所以你需要明确地转换为ushort

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

答案 1 :(得分:1)

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

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

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

  • 7.3.6.2二进制数字促销(“否则,两个操作数都转换为int类型。”)
  • 6.1.2隐式数字转换
  • 7.5.3过载分辨率

答案 2 :(得分:1)

根据this MSDN pageushort s的计算结果类型为int。所以你需要做的是投射计算结果

oldValue - rate * delta

回到ushort

(ushort)(oldValue - rate * delta)

答案 3 :(得分:1)

小于int的较小数据类型的乘法产生int

因此oldValue - rate * delta产生intMath.Max(short.MinValue, int)的最佳重载是:

Math.Max Method (Int32, Int32)

(因为ushort / short可以隐含地扩展到int,无需转换)