ac#クラスライブラリプロジェクト(.net 4)でVisual Studio 2010 SP1 Ultimateを使用していますが、何か気になります...
この方法を考えると:
public void DoSomethingBrilliant(int input)
{
if (input == int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
コード分析から次の警告が表示されます。
CA2233:Microsoft.Usage:「Test.DoSomethingBrilliant(int)」の操作「input+1」のオーバーフローの可能性を修正しました。
input++
最初にその巧妙な例外をスローすることで操作がオーバーフローしないことを確認しているので、それは少し奇妙だと思いましたが、これに変更しました:
public void DoSomethingBrilliant(int input)
{
if (input >= int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
そして確かに警告は消えました。
引数としてintを取得しているので、整数に許可されている最大値よりも大きいかどうかを確認するために、なぜ私の小さな頭脳はすべて混乱していますか?
次に、元のコードに戻り、デバッグに切り替えました。警告なしでビルドされました。好奇心旺盛で好奇心旺盛な...
デバッグとリリースの違いを確認したところ、 [コードの最適化]オプションにチェックマークを付けると、コード分析からの警告がすぐに表示されることがわかりました。
したがって、最適化の結果、 int.MaxValueより大きいかどうかを確認する必要があることを意味します。は?なんで?私は超高密度ですか?intを受け入れるメソッドに渡されるint.MaxValueよりも大きい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
スロー操作の前にたくさんの余分な呼び出しが表示されますが、正直に言うと、それらが何をするのかわかりません。