2010-05-07 93 views
12

我想讀我編譯的C#代碼。C#,奇怪的優化

這是我的代碼:

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

但是!

我們都知道,使用被轉換到這一點:

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

(因爲OleDbCommand的是引用類型)。

但是當我反編譯我的組件(使用.NET 2.0編譯)我得到這個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:; 
    } 

我說的這條線:if ((insertCommand == null) != null)

假設insertCommand爲null。然後第一部分返回true。 (true != null)返回true。那麼處置仍然被忽略?奇怪,非常奇怪。

如果我粘貼在Visual Studio中,ReSharper的已經警告我:表情總是真的...

謝謝!

-Kristof

+0

我誤讀了這個問題,所以刪掉了我的答案。在正確地閱讀你的問題後,我猜想Resharper中存在一個錯誤,我建議嘗試其他反編譯器,看看你得到了什麼結果。 – 2010-05-07 13:21:03

+1

你用什麼工具反編譯?也許你應該試試另一個 – 2010-05-07 13:22:06

回答

12

反編譯有一個bug。這條線

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

應該被反編譯

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

這雖然不必要的冗長,至少是正確的代碼。

的反編譯器可能做到這一點不必要的詳細的版本,因爲C#編譯器通常選擇發射

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

,如果你會寫

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

由於這兩個程序生成的代碼是一樣的,反編譯器並不總是知道哪一個是更明智的代碼來顯示。

意外的原因「!= false「是因爲當我們生成測試是否爲真的IL時,我們可以產生的最快速和最緊湊的代碼是測試它是否不是假的,在IL中False被表示爲零,並且有一個便宜的指令這個東西是零?「

+0

將此稱爲反編譯器中的錯誤是否合法?可能是用戶寫了cod e看起來像第二種情況,所以編譯器沒有真正的方法來知道選擇哪一個。或者你提議編譯器應該避免在這種情況下使用gotos,因爲大多數用戶不使用它們。 – Brian 2010-05-07 19:40:03

+1

@Brian:編譯器無法避免gotos; * if語句是goto *。 if語句只是編寫條件轉移的一種令人愉快的方式;不要自欺欺人地認爲它不是別的。也就是說,反編譯器的一個很好的啓發式就是反編譯爲用戶在不明確時寫入的代碼。錯誤在於將整數比較爲零的反編譯生成爲null,這不是合法的C#。它應該生成爲與false相比較。 – 2010-05-07 20:18:31

+0

對不起,我的意思是說,問你是否提議* de *編譯器應該避免gotos。正如你指出的那樣,這不是問題。 – Brian 2010-05-08 00:44:41

0

當您反編譯代碼時,您不能保證返回原始代碼。當.net代碼被編譯進IL時,它被優化了。有時,當應用程序將IL轉換回C#時,您會看到一些瘋狂的情況。這並不意味着代碼不起作用,而是應用程序(本例中的resharper)如何翻譯IL。

如果您擔心這個問題,我會直接看IL,看看它編譯成什麼。

邊注意:反編譯IL到C#或VB.net不保證編譯。 :)

另一種產品是嘗試Reflector

+0

我已經在使用反射器:) – Snake 2010-05-09 10:31:01

+0

反射器肯定包含很多的錯誤,我自己報了一個,從來沒有得到答覆。 .com/MessageBoard/viewtopic.php?t = 8858 – 2010-05-09 13:22:50