2012-06-06 53 views
2

我正在写一段代码来防止上溢/下溢。在此之前,我尝试:C#Math.Max类型处理

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来做我的比较?

+0

所以对于'USHORT一个= 0; a- = 1;'与'ushort b = 0不同; b = b-1;'(稍后一个失败),有趣......我一直认为这个类型是由左边的值决定的。 –

回答

2

这是因为oldValue - rate * delta的结果类型为int。这是因为运营商+, - ,*和/所定义的“最小数据类型”为int。所以byte,ushort等首先转换为int。然后,结果再次是int。所以你需要明确地投下ushort

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

1

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重载分析
1

this MSDN page,计算与ushort S中的结果类型为int。所以,你需要做的就是投计算

oldValue - rate * delta 

ushort结果:

(ushort)(oldValue - rate * delta) 
1

int乘法较小的数据类型的产生一种int作为结果。

THEREFOR oldValue - rate * delta导致一个intMath.Max(short.MinValue, int)最好过载是:

Math.Max Method (Int32, Int32)

(因为一个ushort/short可以被加宽到int隐含,无需转换)