2013-07-06 62 views
3

溢出行为相同的程序我在.net 3.5运行一个程序使用C#当我运行这个程序在C#中的正常工作差异在C#和VB.Net

try 
{ 
    int i = 2147483647; 

    Console.WriteLine((i * 100/i).ToString()); 

    Console.ReadLine(); 
} 
catch (Exception) 
{     
    throw; 
} 

,我没有得到一个异常(输出“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 

为什么这两种语言之间的不同的行为?

+3

也许因为VB.NET会默认检查溢出,而C#不会呢? – BoltClock

+3

顺便说一下,*没有*关于BODMAS/PEMDAS意味着答案应该是0 - 这是C#如何执行溢出的结果。在这种情况下,(i * 100)= - 100。 –

+0

@MichaelBray:我的解释是,这是一个关于'(i * 100)/ i'和'i *(100/i)'的问题...... –

回答

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

试着改变你的程序是:

try { 
    checked { 
     int i = 2147483647; 
     Console.WriteLine((i * 100/i).ToString()); 
     Console.ReadLine(); 
    } 
} 
catch (Exception) { 
    throw; 
} 

C#不会自动执行算术默认检查。然而,如果你去项目属性...生成选项卡......高级...“[X]检查算术溢出/下溢”,那么你会得到与默认情况下VB.NET相同的行为。

+0

是的 - 我确认IL输出(请参阅我的回复)确实切换到在'checked'块中使用'mul.ovf'而不是'mul'。 –

0

输出是不同的,因为您发布的VB代码是而不是相当于C#代码。 正确的转换是:

Console.WriteLine((i * 100 \ i).ToString()) 

注意,C#执行对整数整数(截断)部门,而在VB中,你必须使用整数除法运算符“\”做同样的整数除法。

(更新:即使使用正确转换的整数除法运算符,我也会在我的测试中得到相同的异常,所以显然它不只是关于运算符)。