Search code examples
c#language-lawyerdispose

Why using Dispose as a normal method is bad?


Trying to figure it out. Someone told me

Dispose is not just a method - it's equivalent to a destructor in other languages.

Ok. Msdn is also very loud about this.

But then

class Test : IDisposable
{
    public string Property { get; set; } = "Test";
    public void Dispose() => Console.WriteLine("Disposed, very scary");
}

class Program
{
    static void Main(string[] args)
    {
        var test = new Test();
        test.Dispose();
        test.Property = "123";  // but it's disposed OMG! do not do this!
        test.Dispose();

        using (var another = new Test())
            for (int i = 0; i < 10; i++)
            {
                another.Dispose();
                GC.Collect(); // or what should I call to make it crash?
            }

        Console.ReadKey();
    }
}

And there are no problems.

What I think about Dispose:

  • it's a normal public method;
  • IDisposable is useful in conjunction with using to automatically call Dispose, nothing more;
  • it's totally fine to put into dispose any code an call it internally at any time if object state properly maintained.

Correct me if I am wrong.

P.S: Downvote means "question is bad/not useful/has problem". If you simply disagree with my thoughts - post comment or answer. It will be useful for people who think as I do right now (because I am wrong? then prove it)


Solution

  • Dispose is just a method, you can call it just like any other method. It is always exposed through the IDisposable interface (yes, obviously you can name a method Dispose without implementing IDisposable, don't do that!).

    However, calling it manually is sometimes a code smell, smell of code that should probably be using using instead. By "manually" here I mean calling Dispose outside of the implementation of another Dispose.

    Calling it twice should also be safe and is documented:

    If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

    (my emphasis)

    Should you be calling Dispose twice? No!. That is also a code smell of code that no longer has control of what it has done and what it has left to do and ends up doing things "just to be sure". Don't do that either!

    So if you write code correctly, sure you can call Dispose manually.