Why exiting "using" invokes unexpected Dispose()?

89 Views Asked by At

Here is my case:

class A : IDisposable
{
    public void Dispose() { Console.WriteLine("A Dispose"); }
}

class B : A
{
    public new void Dispose(){ Console.WriteLine("B Dispose"); }
}

class Program
{
    static void Main(string[] args)
    {
        using (B b = new B())
        {
        }
    }
}

Final output is "A Dispose". I've read some documents which introduce the difference of override and new, and something telling that "using" substantially equals to "try-finally". But I am still can't get answer to why it is not B::Dispose got automatically invoked. Comparingly following's output is "B Dispose"

B b = new B();
try
{
}
finally
{
    b.Dispose();
}

Please help, which did I miss.

1

There are 1 best solutions below

2
Etienne de Martel On BEST ANSWER

According to the C# language specification, for a reference type:

using (ResourceType resource = «expression» ) «statement»

is equivalent to

{
    ResourceType resource = «expression»;
    try {
        «statement»;
    }
    finally {
        IDisposable d = (IDisposable)resource;
        if (d != null) d.Dispose();
    }
}

As you can see, the resource is first cast to IDisposable, which means that A's Dispose is the one called, since B's Dispose is merely hiding it instead of overriding it.

If you want to correctly implement IDisposable in a class hierarchy, see the best practices for this in the documentation.