何时/如何IDisposable.Dispose调用?

时间:2014-08-07 13:11:45

标签: c# idisposable

鉴于以下类实现了DisposeIDisposable.Dispose

internal class DisposableClass : IDisposable
{
    public void Dispose()
    {
    }
    void IDisposable.Dispose()
    {
    }
}

当我调用DisposeableClass.Dispose(通过类的实例)时,调用public void Dispose

DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
    newClass.Dispose();
}

如果将try-finally更改为using语句,则调用IDisposable.Dispose。

using (DisposableClass newClass = new DisposableClass())
{
}

但是NOT the IDisposable.Dispose which I defined

编译器将using语句转换为((IDisposable)newClass).Dispose()。完整的方法名称显示它来自System.IDisposable.Dispose。

IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()

何时会调用IDisposable.Dispose的自定义实现?

请注意,我没有使用这个实际的实现,我知道不应该使用它。但我仍然很好奇在什么时候调用哪个实现。

如果我对每个Dispose方法都有不同的实现方式;什么时候会调用哪个实现?

1 个答案:

答案 0 :(得分:3)

您的处置方法是错误的。您应该查看The Dispose Pattern以了解如何正确执行此操作。

然而...... 要回答你的问题,他们如何/为何被称为......

当您说public void Dispose()时,newClass.Dispose();被调用,因为它是最好的"匹配"对于你所问的。通过它(并且没有变得太复杂),这是因为它是层次结构中最高的,因此是编译器期望您的意思,因为它是最具体的。如果您还没有创建自己的,那么它将通过层次结构来查找Dispose方法。

当您使用using换行时,编译器会生成与此类似的代码:

DisposableClass newClass = new DisposableClass();
try
{
}
finally
{
    ((IDisposable)newClass).Dispose();
}

因此,这将明确调用IDiposable版本。

<强>更新

下面的完整工作示例将提供此输出:

Manually calling newClass.Dispose();
public void Dispose() being called.

Now wrapped in using...
void IDisposable.Dispose() being called.

Manually calling IDisposable.Dispose();
void IDisposable.Dispose() being called.

完整的工作代码(将其粘贴到控制台应用程序并运行):

using System;

namespace zPlayGround
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Manually calling newClass.Dispose();");
            var newClass = new DisposableClass();
            try
            {
            }
            finally
            {
                newClass.Dispose();
            }

            Console.WriteLine("Now wrapped in using...");
            using (var usingClass = new DisposableClass())
            {

            }

            Console.WriteLine("Manually calling IDisposable.Dispose();");
            var demoClass = new DisposableClass();
            try
            {
            }
            finally
            {
                ((IDisposable)newClass).Dispose();
            }
            Console.ReadKey();
        }
    }

    internal class DisposableClass : IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine("public void Dispose() being called.\r\n");
        }
        void IDisposable.Dispose()
        {
            Console.WriteLine("void IDisposable.Dispose() being called.\r\n");
        }
    }
}