C #, странная оптимизация - PullRequest
12 голосов
/ 07 мая 2010

Я пытаюсь прочитать мой скомпилированный код 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 IS null. Тогда первая часть возвращает истину. (true != null) возвращает true. Так тогда утилизации все еще пропущены? Странно, очень странно.

Если я вставлю это в Visual Studio, Resharper уже предупредит меня: выражение всегда верно ...

Спасибо!

-Kristof

Ответы [ 2 ]

12 голосов
/ 07 мая 2010

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

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 голосов
/ 07 мая 2010

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

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

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

Еще один продукт, который стоит попробовать - Отражатель

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