2

Given the following class which implements both Dispose and IDisposable.Dispose:

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

When I make a call to DisposeableClass.Dispose (through an instance of the class), the public void Dispose is called:

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

If you change the try-finally to a using statement, IDisposable.Dispose is called.

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

But NOT the IDisposable.Dispose which I defined.

The compiler translates the using-statement to ((IDisposable)newClass).Dispose(). The full methodname shows it to be from System.IDisposable.Dispose.

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

When will my custom implementation of IDisposable.Dispose be called?

Note that I am not using this actual implementation and I get that this should not be used. But I am still curious as to which implementation gets called when.

If I'd have a different implementation for each of the Dispose methods; which implementation would be called when?

Belogix
  • 8,129
  • 1
  • 27
  • 32
Matthijs
  • 3,162
  • 4
  • 25
  • 46
  • 5
    Why would you do this? You should follow the "Dispose pattern" or at least understand what you are supposed to do. This is just the wrong approach! Dispose Pattern can be found here: http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx – Belogix Aug 07 '14 at 13:14
  • @Belogix: I am in the process of writing a rule which checks classes if they implement either of the Dispose-functions. Given that I was unable to actually call IDisposable.Dispose, I wrote the question. Just for learning purposes. And even if I should follow the Dispose pattern; I am still wondering how and when this method gets executed. Because given from where I am now, the implementation of IDisposable.Dispose seems nothing but redundant to me. – Matthijs Aug 07 '14 at 13:16
  • Sure, but by inheriting `IDisposable` interface you are explicitly saying that there MUST BE a `Dispose` method... You don't need to override / overload / hide do anything funky? – Belogix Aug 07 '14 at 13:17
  • @Matthijs Why doesn't that rule just check for the interface? Your non-explicit method will not be called because it resolved the call, due to `using` generating code that uses the interface directly, into a call to the explicit method. This is just bad code, as if you did this, you'd internally simply call one from the other. – Adam Houldsworth Aug 07 '14 at 13:19
  • While there is no need; there is still the possibility to do so. Skipping any moral grounds as to why you should or should not implement the IDisposable interface this way; how is this method called? – Matthijs Aug 07 '14 at 13:19
  • @AdamHouldsworth: It is actually a more complex rule. It checks if any instances of a class that implement IDisposable interface, calls its' Dispose-Method. One problem I ran into is that, while the class could implement a Dispose-method; it may not be the correct Dispose-method. – Matthijs Aug 07 '14 at 13:21
  • @Matthijs Simply because the `using` statement creates code that uses the `IDisposable` interface directly, then its bound to the most targeted method on call, which is the explicit one. – Adam Houldsworth Aug 07 '14 at 13:21
  • @AdamHouldsworth: is my implementation even called at any point then? – Matthijs Aug 07 '14 at 13:21
  • @Matthijs Not if you use a `using` statement or a reference to `IDisposable` as opposed to your class. See [Explicit Interface Implementation](http://msdn.microsoft.com/en-us/library/ms173157.aspx) documentation. You would need to bridge the methods yourself internally, much like you would do with overloading. – Adam Houldsworth Aug 07 '14 at 13:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/58880/discussion-between-matthijs-and-adam-houldsworth). – Matthijs Aug 07 '14 at 13:34
  • possible duplicate of [C# Interfaces. Implicit implementation versus Explicit implementation](http://stackoverflow.com/questions/143405/c-sharp-interfaces-implicit-implementation-versus-explicit-implementation) – i3arnon Aug 07 '14 at 22:45

1 Answers1

3

Your approach to disposing is wrong. You should look at The Dispose Pattern to understand how to do this properly.

However... To answer your question how / why are they called...

Your public void Dispose() is being called when you say newClass.Dispose(); because it is the best "match" for what you have asked. By that (and without getting too complicated) it is because it is the highest in the hierarchy and therefore the one the compiler expects you to mean because it is the most specific. If you hadn't created your own it would have gone through hierarchy to find a Dispose method.

When you wrap with using the compiler produces code similar to this:

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

This will therefore call the IDiposable version explicitly.

UPDATE

Full working sample below that will give this output:

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.

Full working code (paste this inside a console app and run):

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");
        }
    }
}
Belogix
  • 8,129
  • 1
  • 27
  • 32
  • I know this yes; I already explained that in my question; knowing that a using statement gets translated to this. This still doesn't answer my question. When is IDisposable.Dispose called. The one I wrote? Because given my understanding; there is the possibility to give a different implementation to either of the Dispose-methods I made (Dispose and the IDisposable.Dispose). Say I have done this; which implementation would be called when? – Matthijs Aug 07 '14 at 13:23
  • @Belogix The compiler would not have found the explicit `Dispose` method if the other was missing, because it can only be accessed via an explicit reference to the relevant interface. Also, the compiler writes a little more than that, namely a nested `try-finally`, so I'd probably describe that as "the compiler produces code similar to this". – Adam Houldsworth Aug 07 '14 at 13:25
  • Yours will NEVER be called unless you explicitly call it. I.e. `newClass.Dispose();` This is because you have `IDisposable.Dispose()` which is what the interface `IDisposable` needs to be called. – Belogix Aug 07 '14 at 13:26
  • @AdamHouldsworth - I know, but I am trying to keep this simple because I think the OP is a bit confused anyway and as I mention in the first sentence this isn't the right approach anyway. PS. I changed to mention "the compiler produces code similar to this" to clarify. – Belogix Aug 07 '14 at 13:27
  • But the IDisposable.Dispose() is not called when I use newClass.Dispose(). It calls the first implementation; public void Dispose. Am I really not getting something. How can I tell that the IDisposable.Dispose() is called? The one I explicitly implemented. – Matthijs Aug 07 '14 at 13:29
  • @Matthijs - As far as any caller of your class is concerned you have TWO methods both called `Dispose` with no-way to (easily) tell the two apart. When you call `newClass.Dispose()` it will use **YOUR** one because it belongs solely in your class. When you wrap in `using` the compiler explicitly calls `((IDisposable)newClass).Dispose();` meaning the **OTHER** one is called. So unless you explictly state you want `IDisposable.Dispose` to be called it will default (for lack of a better word) to your one. Hope that is making some sense?! – Belogix Aug 07 '14 at 13:32
  • @Belogix: yes, that makes sense but you are not really getting me I think. Can we continue this in a chat somewhere? [here](http://chat.stackoverflow.com/rooms/58880/discussion-between-matthijs-and-adam-houldsworth) – Matthijs Aug 07 '14 at 13:34