2010-05-07 16 views
12

Sto provando a leggere il mio codice C# compilato.C#, ottimizzazione strana

questo è il mio codice:

using(OleDbCommand insertCommand = new OleDbCommand("...", connection)) 
{ 
    // do super stuff 
} 

Ma!

Sappiamo tutti che un utilizzo si traduce in questo:

{ 
    OleDbCommand insertCommand = new OleDbCommand("...", connection) 
    try 
    { 
     //do super stuff 
    } 
    finally 
    { 
     if(insertCommand != null) 
      ((IDisposable)insertCommand).Dispose(); 
    } 
} 

(dal OleDbCommand è un tipo di riferimento).

Ma quando ho decompilare il mio assemblaggio (compilato con .NET 2.0) ottengo questo in ReSharper:

try 
{ 
    insertCommand = new OleDbCommand("", connection); 
Label_0017: 
    try 
    { 
     //do super stuff 
    } 
    finally 
    { 
    Label_0111: 
     if ((insertCommand == null) != null) 
     { 
      goto Label_0122; 
     } 
     insertCommand.Dispose(); 
    Label_0122:; 
    } 

Sto parlando di questa linea: if ((insertCommand == null) != null).

Diciamo insertCommand IS null. Quindi la prima parte restituisce true. (true != null) restituisce true. Allora, l'eliminazione è ancora saltata? Strano, molto strano.

Se incollo questo in Visual Studio, ReSharper mi avverte già: L'espressione è sempre vero ...

Grazie!

-Kristof

+0

Ho letto male la domanda così cancellata la mia risposta.Dopo aver letto correttamente la tua domanda, immagino che ci sia un bug in Resharper, ti suggerirei di provare qualche altro decompilatore e vedere quali risultati ottieni –

+1

Quale strumento usi per decompilare? Forse dovresti provare con un altro –

risposta

12

Il decompilatore ha un bug. Questa linea

if ((insertCommand == null) != null) 

avrebbe dovuto essere decompilato per

if ((insertCommand == null) != false) 

che, sebbene inutilmente dettagliato, è almeno codice corretto.

Il decompilatore probabilmente fa questa versione inutilmente prolissa, perché il compilatore C# spesso sceglie di emettere

if (x) 
    Y(); 
Z(); 

come se avessi scritto

if (!x) 
    goto L; 
Y(); 
L: Z(); 

Dal momento che il codice generato per entrambi i programmi è la stessa , il decompilatore non sempre sa quale sia il codice più sensibile da visualizzare.

Il motivo dell'imprevisto "!= falso "è perché quando generiamo IL che verifica se qualcosa è vero, il codice più veloce e compatto che possiamo generare è quello di verificare se non è falso. False è rappresentato come zero in IL, e c'è un'istruzione a buon mercato per" è questa cosa zero? "

+0

È legittimo chiamare questo bug nel decompilatore? È possibile che l'utente abbia scritto il merluzzo e che sembrava il secondo caso, quindi il compilatore non ha un modo reale per sapere quale scegliere. O stai proponendo che il compilatore dovrebbe favorire l'eliminazione del gotos in questo tipo di situazione poiché la maggior parte degli utenti non li usa. – Brian

+1

@Brian: il compilatore non ha modo di evitare gotos; * un'istruzione if è un goto *. Un'istruzione if è solo un modo piacevole di scrivere un goto condizionale; non illuderti di pensare che sia qualcosa di diverso da quello. Detto questo, una buona euristica per un decompilatore è decompilare il codice che l'utente ha più probabilmente scritto quando è ambiguo. Il bug è che la decompilazione di un confronto di un numero intero a zero viene generata come confronto con null, che non è C# legale. Dovrebbe essere generato come un confronto con falso. –

+0

Scusate, volevo dire chiedere se stavate proponendo che il compilatore * de * dovrebbe favorire l'eliminazione del gotos. Quale non è il problema, come fai notare. – Brian

0

quando si decompilare codice, non sono garantiti per ottenere il codice originale di nuovo. Quando il codice .net è compilato in IL, è ottimizzato. A volte vedrai qualcosa di pazzo quando un'applicazione traduce l'IL in C#. Questo non significa che il codice non funzioni, è proprio come l'applicazione (in questo caso il resharper) ha tradotto l'IL.

Se siete preoccupati, guarderei direttamente all'IL per vedere in che cosa è stato compilato.

Nota a margine: l'IL decompilato in C# o VB.net non è garantito per la compilazione. :)

Un altro prodotto da provare è Reflector

+0

Io già uso Reflector :) – Snake

+0

Reflector contiene sicuramente molti bug. Ne ho segnalato uno anch'io, e non ho mai avuto nemmeno una risposta. Http: //www.red-gate .com/MessageBoard/viewtopic.php? t = 8858 –