12

I'm trying to read my compiled C# code.

this is my code:

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

But!

We all know that a using gets translated to this:

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

(since OleDbCommand is a reference type).

But when I decompile my assembly (compiled with .NET 2.0) I get this in 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:;
    }

I'm talking about this line: if ((insertCommand == null) != null).

Let's say insertCommand IS null. Then the first part returns true. (true != null) returns true. So Then the disposing is still skipped? Weird, very weird.

If I paste this in Visual Studio, Resharper already warns me: Expression is always true...

Thanks!

-Kristof

4

2 回答 2

12

反编译器有一个错误。这条线

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

应该被反编译成

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

尽管不必要地冗长,但至少是正确的代码。

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

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

好像你写过

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

由于为这两个程序生成的代码是相同的,反编译器并不总是知道哪一个是更明智的显示代码。

出现意外“!= false”的原因是因为当我们生成测试某事是否为真的IL时,我们能生成的最快、最紧凑的代码就是测试它是否为假。False 在 IL 中表示为 0,并且有一条廉价指令用于“这东西是零吗?”

于 2010-05-07T14:15:51.203 回答
0

当你反编译代码时,你不能保证得到原始代码。当 .net 代码编译到 IL 中时,它会被优化。有时,当应用程序将 IL 转换回 C# 时,您会看到一些疯狂的情况。这并不意味着代码不起作用,这只是应用程序(在本例中为 resharper)翻译 IL 的方式。

如果你担心它,我会直接看 IL 看看它被编译成什么。

旁注:不保证将 IL 反编译为 C# 或 VB.net 即可编译。:)

另一种尝试的产品是反射器

于 2010-05-07T13:54:06.553 回答