HonanLi
HonanLi

Reputation: 99

Why exiting "using" invokes unexpected Dispose()?

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.

Upvotes: 1

Views: 97

Answers (1)

Etienne de Martel
Etienne de Martel

Reputation: 36851

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.

Upvotes: 2

Related Questions