【问题标题】:C# Math.Max type handlingC# Math.Max 类型处理
【发布时间】:2012-06-06 14:20:14
【问题描述】:

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

【问题讨论】:

  • 所以对于ushort a=0; a-=1;ushort b=0; b=b-1; 是不同的东西(后来失败了),有趣……我一直以为类型是由左值决定的。

标签: c# overflow type-conversion underflow


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    根据this MSDN pageushorts 的计算结果类型是 int。所以你需要做的就是把计算的结果投射出来

    oldValue - rate * delta
    

    ushort:

    (ushort)(oldValue - rate * delta)
    

    【讨论】:

      【解决方案3】:

      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 过载分辨率

      【讨论】:

        【解决方案4】:

        int 更小的数据类型相乘会产生int 作为结果。

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

        Math.Max Method (Int32, Int32)

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-10
          • 1970-01-01
          • 2021-07-29
          • 1970-01-01
          • 2016-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多