Sto usando Visual Studio 2010 SP1 finale su AC# progetto di libreria di classi (.net 4) e sono curioso di sapere qualcosa ...Perché dovrei controllare per maggiore di Int32.MaxValue?
Dato questo metodo:
public void DoSomethingBrilliant(int input)
{
if (input == int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
ottengo questo avvertimento da parte analisi del codice:
CA2233: Microsoft.Usage: correggere la potenziale overflow 'ingresso + 1' l'operazione 'Test.DoSomethingBrilliant (int)'.
ho pensato a me, che è un po 'strano dal momento che sto controllando che l'operazione non sarà in overflow input++
lanciando tale eccezione sgargianti all'inizio, ma ho cambiato a questo:
public void DoSomethingBrilliant(int input)
{
if (input >= int.MaxValue)
throw new ArgumentOutOfRangeException("input");
input++;
Console.WriteLine(input);
}
e sicuramente l'avviso è andato via.
Ora il mio piccolo cervello è tutto confuso perché dato che sto ottenendo un argomento int perché il controllo per vedere se è maggiore del valore massimo consentito per un intero fornisce mai alcun valore?
Quindi sono tornato al bit originale del codice e sono passato al debug e l'ho creato senza avvertimento! Curiouser e curioser ...
ho controllato le differenze tra il debug e rilascio e scoperto che se ho spuntare il codice Ottimizzare opzione avvertimento da analisi del codice apre right back up.
Quindi l'ottimizzazione si traduce in qualcosa che significa che è necessario controllare maggiore di int.MaxValue. Eh? Perché? Sono super denso? Cosa ha fatto l'ottimizzazione che significa che potrei ottenere un int più grande di int.MaxValue passato in un metodo che accetta un int?
Oppure, questo è solo un bug nella funzionalità di analisi del codice?
Aggiornamento
Ecco l'IL per la versione "non ottimizzata" (dove l'analisi del codice ottiene di destra):
.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
e qui è per la versione ottimizzata (dove ottiene sbagliato):
.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
vedo un sacco di chiamate in più prima dell'operazione tiro, ma ho intenzione di essere onesto - non ho idea di che cosa loro fanno!
L'analizzatore di codice vede probabilmente gli operatori di disuguaglianza come avere più gravitas di semplice uguaglianza. Cerco certamente di ridurre gran parte dell'universo dei valori quando eseguo i controlli di sicurezza. – bluevector
Sono interessato perché lo farebbe correttamente su un assembly "debug" non ottimizzato? – kmp
@kmp: non vorrei dire. Mi chiedo se '==' sia ottimizzato in qualche modo strano. Hai mai visto l'IL? –