C# Try-Finally-Dispose和Using语句之间的区别
我一直在潜心研究微软的代码分析,偶然发现了一些非常有趣的东西。NET似乎使用了两种不同类型的Dispose,具体取决于它的调用方式。采取以下两种选择:C# Try-Finally-Dispose和Using语句之间的区别,c#,.net,dispose,C#,.net,Dispose,我一直在潜心研究微软的代码分析,偶然发现了一些非常有趣的东西。NET似乎使用了两种不同类型的Dispose,具体取决于它的调用方式。采取以下两种选择: public void SqlConnectionUsing() { using (SqlConnection connection = new SqlConnection()) { } } public void SqlConnectionFinally() { SqlConnection connection
public void SqlConnectionUsing()
{
using (SqlConnection connection = new SqlConnection())
{
}
}
public void SqlConnectionFinally()
{
SqlConnection connection = new SqlConnection();
try
{
}
finally
{
connection.Dispose();
}
}
这两个选项被翻译成完全相同的东西;在汇编期间。using成为try finally语句,在finally语句中调用Dispose方法
我说的是一种处置方法;因为什么样的dispose方法取决于您编写代码的方式
当转到using语句时,会调用callvirt instance void[mscorlib]System.IDisposable::Dispose()
(这是确切的IL行)
并手动使用try finally选项,dispose语句更改为:callvirt instance void[System]System.ComponentModel.Component::dispose()
为什么调用的dispose函数不同
如果需要,我可以添加整个IL代码。在编译过程中,使用语句的转换为:
try
{
}
finally
{
((IDisposable)connection).Dispose();
}
实际上,您可以在同一个类中定义两个Dispose()
方法,一个显式用于IDisposable
接口,另一个用于类方法:
public class X : IDisposable
{
void IDisposable.Dispose() { }
public void Dispose() { }
}
但是,如果让这些方法有不同的行为,你真的会毁了别人的一天
此外,您可以在未实现IDisposable
的类中创建Dispose()
方法,但无法使用语句将其放置在中。这是因为使用始终使用IDisposable.Dispose()
并从那里向上(因此它实际上是一个接口方法调用)
事实上:
using (IDisposable x = ...)
{ }
在最后,您实际上是在调用该方法,因为这是SqlConnection
FYI使用时可用的最高Dispose
方法,带有null
检查。这是C规范中的8.13。这解释了很多!谢谢。另外@weston:我不知道,很高兴知道。使用有意义吗
调用Dispose本身;不执行nullcheck当然会导致异常。@Matthijs-而且IDisposable
实现者有一个要注意的问题;请看,实际上该行为并不完全等同于((IDisposable)connection.Dispose()
,而是CallDispose(connection)
,假设void CallDispose(T it),其中T:IDisposable{if(it!=null)it.Dispose();}
。ifit
是一个带有IDisposable
实现,前者会将其装箱,但后者不会。请注意,由于C#使用
将参数的副本处置到,因此即使在这样做会提高效率的情况下,也不可能有效地使用带有非平凡的Dispose
方法的结构。