2012-06-27 76 views
13

我使用Visual Studio 2010 SP1旗艦版在C#類庫項目(.NET 4),我很好奇的東西...爲什麼我需要檢查大於Int32.MaxValue?

鑑於這種方法:

public void DoSomethingBrilliant(int input) 
{ 
    if (input == int.MaxValue) 
     throw new ArgumentOutOfRangeException("input"); 

    input++; 

    Console.WriteLine(input); 
} 

我得到這樣的警告代碼分析:

CA2233:Microsoft.Usage:糾正操作 'Test.DoSomethingBrilliant(int)的' '輸入+ 1' 中的可能的溢出。

我心想,這是一個有點奇怪,因爲我檢查了input++操作不會拋出該異常時髦一開始溢出,但我把它改成這樣:

public void DoSomethingBrilliant(int input) 
{ 
    if (input >= int.MaxValue) 
     throw new ArgumentOutOfRangeException("input"); 

    input++; 

    Console.WriteLine(input); 
} 

當然,警告消失了。

現在我的小腦袋全部都感到困惑,因爲我得到一個int作爲一個參數,爲什麼要檢查它是否大於一個整數提供的任何值所允許的最大值?

然後我又回到原來的代碼位置,切換到調試模式,並且沒有警告就編譯出來! curiouser和古董...

我檢查了調試和發佈之間的差異,發現如果我選擇優化代碼選項,代碼分析的警告立即彈出。

因此,優化結果意味着我需要檢查大於int.MaxValue。咦?爲什麼?我是超級密集的嗎?這樣做的優化意味着我可能會得到一個大於int.MaxValue的int,並將其傳遞給接受int的方法?

或者,這只是代碼分析功能中的一個錯誤?

更新

這裏是IL爲「未優化」的版本(這裏的代碼分析得到它的權利):

.method public hidebysig instance void DoSomethingBrilliant(int32 input) cil managed 
{ 
    // Code size  40 (0x28) 
    .maxstack 2 
    .locals init ([0] bool CS$4$0000) 
    IL_0000: nop 
    IL_0001: ldarg.1 
    IL_0002: ldc.i4  0x7fffffff 
    IL_0007: ceq 
    IL_0009: ldc.i4.0 
    IL_000a: ceq 
    IL_000c: stloc.0 
    IL_000d: ldloc.0 
    IL_000e: brtrue.s IL_001b 
    IL_0010: ldstr  "input" 
    IL_0015: newobj  instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string) 
    IL_001a: throw 
    IL_001b: ldarg.1 
    IL_001c: ldc.i4.1 
    IL_001d: add 
    IL_001e: starg.s input 
    IL_0020: ldarg.1 
    IL_0021: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0026: nop 
    IL_0027: ret 
} // end of method Test::DoSomethingBrilliant 

,在這裏它是爲優化版本(它得到它錯了):

.method public hidebysig instance void DoSomethingBrilliant(int32 input) cil managed 
{ 
    // Code size  31 (0x1f) 
    .maxstack 8 
    IL_0000: ldarg.1 
    IL_0001: ldc.i4  0x7fffffff 
    IL_0006: bne.un.s IL_0013 
    IL_0008: ldstr  "input" 
    IL_000d: newobj  instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string) 
    IL_0012: throw 
    IL_0013: ldarg.1 
    IL_0014: ldc.i4.1 
    IL_0015: add 
    IL_0016: starg.s input 
    IL_0018: ldarg.1 
    IL_0019: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_001e: ret 
} // end of method Test::DoSomethingBrilliant 

我看到一堆額外的電話投擲操作之前,但我會說實話 - 我不知道什麼他們是這樣!

回答

8

或者,這只是代碼分析功能中的一個錯誤?

看起來像。老實說,讓這種代碼分析變得完美是非常棘手的,這並不奇怪。鑑於任何特定的int不能大於int.MaxValue,>===是絕對等價的。

+0

代碼分析器可能看到不平等運營商具有比簡單的平等更莊重。當我進行安全檢查時,我當然會試圖削減儘可能多的價值觀。 – bluevector

+0

我感興趣的是爲什麼它會在非優化的「調試」程序集中正確使用它? – kmp

+0

@kmp:不想說。我懷疑'=='是否以某種奇怪的方式進行了優化。你有沒有看過IL? –

1

參見這些代碼段:

if (x == int.MaxValue) return; 
// x != int.MaxValue 

if (x >= int.MaxValue) return; 
// x < int.MaxValue 

// x < int.MaxValue 
// rewrite 
// x + 1 <= int.MaxValue 
x++; 
// x <= int.MaxValue 

x的後置條件++示出了(通過推導),該 前提必須是:

x < int.MaxValue 

只能在情況下,建立你檢查:

x >= int.MaxValue 
相關問題