繁体   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