我使用C#在.Net 3.5中运行了一个程序,运行正常
try
{
int i = 2147483647;
Console.WriteLine((i * 100 / i).ToString());
Console.ReadLine();
}
catch (Exception)
{
throw;
}
当我在C#中运行该程序时,我没有得到异常(它输出“0”)。但是,当我在VB.Net中运行此程序时,会导致"Arithmetic operation resulted in an overflow"
异常
Try
Dim i As Integer = 2147483647
Console.WriteLine((i * 100 / i).ToString())
Console.ReadLine()
Catch ex As Exception
Throw
End Try
为什么这两种语言之间存在不同的行为?
答案 0 :(得分:5)
或许看看IL会澄清......简化你的代码:
C#:
int i = 2147483647;
int v = (i * 100 / i);
生成以下IL:
IL_0001: ldc.i4 FF FF FF 7F
IL_0006: stloc.0 // i
IL_0007: ldloc.0 // i
IL_0008: ldc.i4.s 64
IL_000A: mul
IL_000B: ldloc.0 // i
IL_000C: div
IL_000D: stloc.1 // v
而VB版本:
Dim i As Integer = 2147483647
Dim v As Integer
v = i * 100 / i
生成这个IL,略有不同:
IL_0001: ldc.i4 FF FF FF 7F
IL_0006: stloc.0 // i
IL_0007: ldloc.0 // i
IL_0008: ldc.i4.s 64
IL_000A: mul.ovf
IL_000B: conv.r8
IL_000C: ldloc.0 // i
IL_000D: conv.r8
IL_000E: div
IL_000F: call System.Math.Round
IL_0014: conv.ovf.i4
IL_0015: stloc.1 // v
正如您所看到的,VB正在调用mul.ovf
,这是“乘法,检查溢出”,而C#正在调用mul
,而不会检查溢出。
也许它没有回答你的问题,因为为什么 C#以一种方式做,而VB则是另一种方式,但至少它解决了为什么会发生这种情况。 :)
修改:请参阅the answer by aquinas以获取“为什么”。
答案 1 :(得分:1)
尝试将程序更改为:
try {
checked {
int i = 2147483647;
Console.WriteLine((i * 100 / i).ToString());
Console.ReadLine();
}
}
catch (Exception) {
throw;
}
默认情况下,C#不会自动执行算术检查。但是,如果你转到项目属性... Build Tab..Advanced ...“[X] Check For Arithmetic overflow / underflow”,那么你将获得与VB.NET相同的行为。
答案 2 :(得分:0)
输出不同,因为您发布的VB代码不等同于C#代码。 正确的转换是:
Console.WriteLine((i * 100 \ i).ToString())
请注意,C#对整数执行整数(截断)除法,而在VB中,您必须使用整数除法运算符'\'来执行相同的整数除法。
(更新:即使使用正确转换的整数除法运算符,我在测试中也得到相同的异常,所以显然它不仅仅是关于运算符)。