Try-Finally Dispose和Using-statement的区别

本文关键字:区别 Using-statement Dispose Try-Finally | 更新日期: 2023-09-27 18:15:40

我一直在钻研微软的代码分析,并偶然发现了一些非常有趣的事情。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方法。

我说a dispose method;因为哪种处置方法取决于您编写代码的方式。

当去using-statement时,调用到callvirt instance void [mscorlib]System.IDisposable::Dispose()(它是确切的il线)。

手动选择try-finally选项,dispose语句变为:callvirt instance void [System]System.ComponentModel.Component::Dispose() .

为什么有一个不同的处置函数被调用?

如果需要,我可以添加整个il代码。

Try-Finally Dispose和Using-statement的区别

在编译过程中,using语句转换为:

try
{
}
finally
{
    ((IDisposable)connection).Dispose();
}

实际上可以在同一个类中定义两个Dispose()方法,一个显式地用于IDisposable接口,还有一个类方法:

public class X : IDisposable
{
    void IDisposable.Dispose() { } 
    public void Dispose() { }
}
但是,如果让这些方法有不同的行为,你真的会毁了别人的一天。

此外,您可以在不实现IDisposable的类中创建Dispose()方法,但您将无法将其放置在using语句中。

这是因为using总是使用IDisposable.Dispose()并从那里向上(所以它实际上是一个接口方法调用)。

实际上是:

using (IDisposable x = ...)
{ }

在最后,您实际上调用Component.Dispose()方法,因为这是SqlConnection的最高可用Dispose方法。