2

我正在编写一段代码来防止 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

4 回答 4

2

这是因为oldValue - rate * delta' 的结果是类型int。这是因为定义运算符 +、-、* 和 / 的“最小数据类型”是int. 所以byte,ushort等被转换为int第一。然后,结果又是一个int. 所以你需要明确地转换为ushort.

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

于 2012-06-06T14:25:50.827 回答
1

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

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

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

  • 7.3.6.2 二进制数字提升(“否则,两个操作数都转换为 int 类型。”)
  • 6.1.2 隐式数值转换
  • 7.5.3 过载分辨率
于 2012-06-06T14:27:50.693 回答
1

根据这个 MSDN page,用 s 计算的结果类型ushort是 int。所以你需要做的是转换计算的结果

oldValue - rate * delta

回到ushort

(ushort)(oldValue - rate * delta)
于 2012-06-06T14:28:49.843 回答
1

int比结果更小的数据类型的乘法int

因此oldValue - rate * delta导致一个int和最好的过载Math.Max(short.MinValue, int)是:

Math.Max Method (Int32, Int32)

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

于 2012-06-06T14:33:34.893 回答