Estoy utilizando Visual Studio 2010 SP1 último en el AC# proyecto de biblioteca de clases (4 .net) y estoy curiosidad por algo ...¿Por qué debería comprobar si tengo un valor mayor que Int32.MaxValue?
Teniendo en cuenta este método:
public void DoSomethingBrilliant(int input)
{
if (input == int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
consigo esta advertencia de análisis de código:
CA2233: Microsoft.Usage: Corregir el desbordamiento potencial en 'de entrada + 1' la operación en 'Test.DoSomethingBrilliant (int)'.
pensé para mí, que es un poco extraño, ya que estoy comprobando que la operación no tendrá input++
desbordamiento lanzando esa excepción elegante al principio pero cambiado a esto:
public void DoSomethingBrilliant(int input)
{
if (input >= int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
y, por supuesto, la advertencia desapareció.
Ahora mi pequeño cerebro está confundido porque dado que estoy obteniendo un int como argumento, ¿por qué la comprobación para ver si es mayor que el valor máximo permitido para un número entero alguna vez proporciona algún valor?
Luego volví al código de código original y cambié a depuración y ¡se construyó sin la advertencia! Curioso y curioso ...
Comprobé las diferencias entre la depuración y la versión y encontré que si selecciono la opción Optimizar el código, la advertencia del análisis del código aparece de nuevo.
Por lo tanto, la optimización da como resultado algo que significa que necesito comprobar más de int.MaxValue. ¿Huh? ¿Por qué? ¿Estoy siendo super denso? ¿Qué ha hecho la optimización que significa que podría obtener un int mayor que int.MaxValue pasado a un método que acepta un int?
O, ¿esto es solo un error en la función de análisis de código?
actualización
Aquí está la IL para la versión "sin optimizar" (donde el análisis de código lo hace bien):
.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
y aquí es para la versión optimizada (donde se pone es malo):
.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
veo un montón de llamadas adicionales antes de la operación tiro, pero voy a ser honesto - no tengo ni idea de lo ¡ellas hacen!
El analizador de código, probablemente ve los operadores de desigualdad como tener más seriedad que la igualdad simple. Ciertamente trato de cortar tanto del universo de valores cuando hago controles de seguridad. – bluevector
Me interesa saber por qué lo haría bien en un ensamblado de "depuración" no optimizado. – kmp
@kmp: No me gustaría decirlo. Me pregunto si '==' está optimizado de alguna manera extraña. ¿Has mirado el IL en absoluto? –