Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Try-Finally-Dispose和Using语句之间的区别_C#_.net_Dispose - Fatal编程技术网

C# Try-Finally-Dispose和Using语句之间的区别

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

我一直在潜心研究微软的代码分析,偶然发现了一些非常有趣的东西。NET似乎使用了两种不同类型的Dispose,具体取决于它的调用方式。采取以下两种选择:

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();}
。if
it
是一个带有
IDisposable
实现,前者会将其装箱,但后者不会。请注意,由于C#使用
将参数的副本处置到
,因此即使在这样做会提高效率的情况下,也不可能有效地使用带有非平凡的
Dispose
方法的结构。