Home > Software engineering >  Why exiting "using" invokes unexpected Dispose()?
Why exiting "using" invokes unexpected Dispose()?

Time:02-23

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.

CodePudding user response:

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.

  • Related