2013-07-06 58 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中,你必須使用整數除法運算符「\」做同樣的整數除法。

(更新:即使使用正確轉換的整數除法運算符,我也會在我的測試中得到相同的異常,所以顯然它不只是關於運算符)。