我在c#类库项目(.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作为参数,为什么要检查它是否大于允许整数提供任何值的最大值?
然后我回到原来的代码并切换到调试,它没有警告就构建了! Curiouser和curioser ......
我检查了调试和发布之间的差异,发现如果我勾选优化代码选项,代码分析的警告会立即弹回。
因此,优化会导致我需要检查的内容大于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
我在投掷操作之前看到了一堆额外的调用,但我会说实话 - 我不知道他们做了什么!
答案 0 :(得分:7)
或者,这只是代码分析功能中的一个错误吗?
看起来像。说实话非常令人惊讶 - 让这种代码分析变得完美是非常棘手的。鉴于任何特定的int
不能大于int.MaxValue
,>=
和==
肯定是等效的。
答案 1 :(得分: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