В C#, странная оптимизация

Я пытаюсь прочитать мой код 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 уже предупреждает меня: выражение всегда истинно...

спасибо!

-Кристоф

2 ответов


декомпилятор имеет ошибку. Эта строка

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

должен был быть декомпилирован в

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

что, хотя и излишне многословно, является, по крайней мере, правильным кодом.

декомпилятор, вероятно, делает это излишне многословной версией, потому что компилятор C# часто выбирает испускать

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

как будто ты написал

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

поскольку код, сгенерированный для обеих программ, одинаков, декомпилятор не всегда знает, какой из них более разумный код для отображения.

причина неожиданного "!= false " потому что, когда мы генерируем IL, который проверяет, является ли что-то истинным, самый быстрый и компактный код, который мы можем создать, - это проверить, не является ли он ложным. False представляется как ноль в IL, и есть дешевая инструкция для "Является ли эта вещь нулевой?"


когда вы декомпилируете код, вы не гарантированно получите исходный код обратно. Когда .net-код компилируется в IL, он оптимизируется. Иногда вы увидите некоторые сумасшедшие, когда приложение переводит IL обратно в C#. Это не означает, что код не работает, это просто то, как приложение (resharper в этом случае) перевело IL.

Если вы беспокоитесь об этом, я бы посмотрел прямо на IL, чтобы увидеть, во что он был скомпилирован.

боковое Примечание: декомпилированный IL в C# или VB.net не гарантируется компиляция. :)

еще один продукт, чтобы попытаться это отражатель