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 равен нулю. Тогда первая часть возвращает истину. (true != null)
возвращается true
, Значит, тогда утилизация все еще пропущена? Странно, очень странно.
Если я вставлю это в Visual Studio, Resharper уже предупреждает меня: выражение всегда верно...
Спасибо!
-Kristof
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#. Это не означает, что код не работает, это просто то, как приложение (в данном случае, более резкое) преобразовало IL.
Если вы беспокоитесь об этом, я бы посмотрел непосредственно на IL, чтобы увидеть, во что он был скомпилирован.
Примечание: декомпилированный IL в C# или VB.net не гарантированно компилируется.:)
Еще один продукт - Reflector