2010-05-07 13 views
12

Ich versuche, meinen kompilierten C# -Code zu lesen.C#, seltsame Optimierung

dies ist mein Code:

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

Aber!

Wir alle wissen, dass eine Verwendung zu dieser übersetzt wird:

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

(seit OleDbCommand ist ein Referenz-Typ).

Aber wenn ich meine Montage decompile (kompiliert mit .NET 2.0) bekomme ich diese 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:; 
    } 

ich über diese Linie rede: if ((insertCommand == null) != null).

Nehmen wir an, insertCommand ist null. Dann gibt der erste Teil wahr zurück. (true != null) gibt true zurück. Also dann wird die Entsorgung noch übersprungen? Seltsam, sehr komisch.

Wenn ich das in Visual Studio einfügen, ReSharper schon warnt mich: Ausdruck immer wahr ist ...

Dank!

-Kristof

+0

Ich habe die Frage falsch gelesen, löschte meine Antwort. Nach dem Lesen Ihrer Frage richtig, würde ich vermuten, dass es einen Fehler in Resharper ist, würde ich vorschlagen, versuchen Sie einen anderen Decompiler und sehen, welche Ergebnisse Sie erhalten. –

+1

Welches Werkzeug benutzen Sie um zu dekompilieren? Vielleicht sollten Sie einen anderen versuchen –

Antwort

12

Der Decompiler hat einen Fehler. Diese Linie

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

haben sollte

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

die, wenn auch unnötig ausführlich, zu

dekompilierten mindestens richtigen Code ist.

Der Decompiler wahrscheinlich tut dies unnötig ausführliche Version, da der C# Compiler oft

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

, als ob Sie

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

geschrieben hatte auszusenden wählt Da die für beide Programme generierten Code gleich ist , der Decompiler weiß nicht immer, welcher der sinnvollere Code ist.

Der Grund für das Unerwartete "!= false "ist, weil, wenn wir IL generieren, die testet, ob etwas wahr ist, der schnellste und kompakteste Code, den wir erzeugen können, ist zu testen, ob es nicht falsch ist. Falsch wird in IL als Null dargestellt, und es gibt eine billige Anweisung für" ist Dieses Ding Null?

+0

Ist es legitim, dies einen Fehler im Decompiler zu nennen? Es ist möglich, dass der Benutzer cod e, das wie der 2. Fall aussah, also hat der Compiler keine echte Möglichkeit zu wissen, welchen er wählen soll. Oder schlagen Sie vor, dass der Compiler das Vermeiden von GOTOS in dieser Art von Situation vorzieht, da die meisten Benutzer sie nicht verwenden. – Brian

+1

@Brian: Der Compiler hat keine Möglichkeit, Gotos zu vermeiden; * Eine if-Anweisung ist ein Goto *. Eine if-Anweisung ist nur eine angenehme Art, einen bedingten goto zu schreiben; Mach dir keine Gedanken darüber, dass es etwas anderes ist. Das heißt, eine gute Heuristik für einen Decompiler besteht darin, zu dem Code zu dekompilieren, den der Benutzer wahrscheinlicher geschrieben hat, wenn er nicht eindeutig ist. Der Fehler besteht darin, dass die Dekompilierung eines Vergleichs einer Ganzzahl auf Null als Vergleich mit null erzeugt wird, was kein legales C# ist. Es sollte als ein Vergleich zu false generiert werden. –

+0

Sorry, ich wollte sagen fragen, wenn Sie vorschlagen, dass der * de * Compiler sollte vermeiden gotos. Welches ist nicht das Problem, wie Sie darauf hinweisen. – Brian

0

, wenn Sie Code dekompilieren, Sie sind nicht garantiert wieder den ursprünglichen Code zu erhalten. Wenn .net-Code in IL kompiliert wird, wird es optimiert. Manchmal werden Sie etwas verrückt sehen, wenn eine Anwendung die IL zurück in C# übersetzt. Dies bedeutet nicht, dass der Code nicht funktioniert, es ist nur, wie die Anwendung (in diesem Fall nachgeschärft) die IL übersetzt.

Wenn Sie sich Sorgen machen, würde ich direkt in die IL schauen, um zu sehen, in was es kompiliert wurde.

Side Hinweis: dekompilierte IL in C# oder VB.net ist nicht garantiert, zu kompilieren. :)

Ein weiteres Produkt ist zu versuchen, Reflector

+0

Ich benutze bereits Reflektor :) – Snake

+0

Reflector enthält definitiv viele Fehler.Ich habe einen selbst gemeldet, und bekam nie sogar eine Antwort. Http: //www.red-gate .com/MessageBoard/viewtopic.php? t = 8858 –