[英]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.