C#,奇怪的优化

Sna*_*ake 12 .net c# language-design using-statement c#-2.0

我正在尝试阅读我编译的C#代码.

这是我的代码:

using(OleDbCommand insertCommand = new OleDbCommand("...", connection))
{
   // do super stuff
}
Run Code Online (Sandbox Code Playgroud)

但!

我们都知道使用被转换为:

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

(因为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:;
    }
Run Code Online (Sandbox Code Playgroud)

我在说这句话:if ((insertCommand == null) != null).

假设insertCommand为null.然后第一部分返回true.(true != null)回报true.那么处置仍然被跳过?奇怪,非常奇怪.

如果我在Visual Studio中粘贴它,Resharper已经警告过我:表达总是如此......

谢谢!

-Kristof

Eri*_*ert 12

反编译器有一个bug.这条线

if ((insertCommand == null) != null) 
Run Code Online (Sandbox Code Playgroud)

应该被反编译成

if ((insertCommand == null) != false)
Run Code Online (Sandbox Code Playgroud)

虽然不必要地冗长,但至少是正确的代码.

反编译器可能会做这个不必要的冗长版本,因为C#编译器经常选择发出

if (x)
   Y();
Z();
Run Code Online (Sandbox Code Playgroud)

好像你写的那样

if (!x)
    goto L;
Y();
L: Z();
Run Code Online (Sandbox Code Playgroud)

由于为两个程序生成的代码是相同的,因此反编译器并不总是知道哪一个是要显示的更合理的代码.

意外的"!= false"的原因是因为当我们生成测试某些内容是否为真的IL时,我们可以生成的最快和最紧凑的代码是测试它是否为假.在IL中,False表示为零,并且有一个便宜的指令"这个零是什么?"