[英]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.