簡體   English   中英

C#,奇怪的優化

[英]C#, weird optimization

我正在嘗試閱讀我編譯的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

反編譯器有一個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表示為零,並且有一個便宜的指令“這個零是什么?”

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

如果你擔心它,我會直接看IL,看看它被編譯成了什么。

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

另一個嘗試的產品是Reflector

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM