9

I recently implemented a class like:

class TestClass : IDisposable
{
    RegistryKey m_key;
    public TestClass()
    {
        m_key = Registry.CurrentUser.OpenSubKey("Software", false);
    }

    public void Dispose()
    {
        // m_key.Dispose();
        IDisposable disp = m_key;
        disp.Dispose();
    }
}

If I uncomment the direct call to Dispose, I get error CS0117 ("'Microsoft.Win32.RegistryKey' does not contain a definition for 'Dispose'"). Some Googling led me to this thread, where I learned what was going on, so I now understand the mechanics of it. The MSDN documentation suggests that the author would prefer that I call Close() instead of Dispose(), but doesn't explain why.

What is the purpose of this pattern (which I think I've seen it in the IO classes as well)? In light of the fact that this was an intentional decision by the class author, how bad is the code above (the call to Dispose through the IDisposable interface)? It can't be too bad - after all, it's what would happen in a using statement, right?

[edits: 1) changed title from "non-public" to "explicit" 2) removed the explicit implementation from my code, accidentally left in from experimentation]

bmm6o
  • 6,187
  • 3
  • 28
  • 55

2 Answers2

16

This is called explicit interface implementation. In your example since you define the Dispose() method as "void IDisposable.Dispose()" you are explicitly implementing the IDisposable interface as well.

This is normally done to avoid collisions. If Microsoft ever wanted to add another Dispose() method that did something else to RegistryKey they wouldn't be able to unless they used explicit implementation of that interface.

This is done often with the generic IEnumerable<T> interface. It requires you to also implement the non-generic interface IEnumerable. The only member in these two interfaces is GetEnumerator, with the generic one being more useful, so its usually implemented like this:

public clas SomeClass : IEnumerable<SomeOtherClass>
{
    public IEnumerator<SomeOtherClass> GetEnumerator ()
    {
        ...
    }

    IEnumerator IEnumerable.GetEnumerator ()
    {
        return GetEnumerator ();
    }
}

This way when you call an object of SomeClass's GetEnumator method, it calls the generic version, since the other one was implemented explicitly, allowing us to get the strong-typing generics allow.

See pages 166-169 of Programming C# by Jesse Liberty (I've got the fourth edition).

Mark A. Nicolosi
  • 82,413
  • 11
  • 44
  • 46
-3

Most people don't agree with me, but I like using explicit interface implementation for all interfaces. I want to make it clear whether I'm writing a method to be called on my object or on my interface.

This is painful if you have a reference to the object and want to call an interface method (like the above example), but I mitigate it by writing:

class C : IDisposable
{
    public IDisposable IDisposable { get { return this; } }
    void IDisposable.Dispose() { }
}

which means that calling the method on C looks like:

C c = ...
c.IDisposable.Dispose();

The compiler parses this as "Call the IDisposable property on C, then call the Dispose() method on the result" but I read it as "Call the IDisposable.Dispose() method on C" which seems natural here.

This approach can get ugly when using generic interfaces, unfortunately.

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
  • Same here on the explicit interfaces. Generics make it very tough sometimes. – JaredPar Jan 03 '09 at 03:48
  • 35
    Eek - using explicit interface implementation not only makes it harder for the caller without workarounds like yours above, but it also screws up inheritance - you get into tricky situations if a derived class wants to override an interface method. I avoid it when I can. – Jon Skeet Jan 03 '09 at 09:19
  • Inheritable classes which implement interfaces should either do so with virtual public members (in those cases where the members should be accessible as class members) or with virtual protected members whose name is a modified form of the interface member name or signature. VB.NET allows the latter to be done directly `Protected Overridable Sub Foo_Impl() Implements IInterface.Foo` but in C# the best one can do is define a protected virtual method to hold the "guts" of the interface, and have the interface implementation do nothing but chain to that. – supercat May 03 '13 at 16:29
  • 2
    This suggestion constitutes bad programming practice. A class implements an interface because it *is* an instance of that interface. The author's argument about needing explicit casting would apply equally to all the methods inherited from the parent class -- you shouldn't be able to call parent methods unless you cast to the parent class type. That would be strange -- the point of inheritance is that this class is that parent class. The difference between a parent class and an interface is a technical difference to avoid diamonds in the inheritance tree, not a semantic one. Don't escalate it! – srm Oct 30 '13 at 23:46
  • @JonSkeet I know it's a long time ago. But I would be really interested in why you'd aviod it when you can. Especially concerning with [this](http://www.codeproject.com/Articles/392516/Why-I-use-explicit-interface-implementation-as-a-d) codeproject article. – Alex Endris Sep 09 '14 at 06:52
  • 1
    @Qudeid: It becomes a pain when trying to override the implementation in a subclass, for one thing (as noted). And while you often want to decouple the callers from a particular implementation, sometimes they really *do* want that implementation, for good reasons... at which point you've made their life much harder. The "removing methods from an interface" point is an interesting one, but given that you'd have to remove all the callers of the interface method first, removing the implementations too isn't that much work. I'll stick to implicit implementation most of the time. – Jon Skeet Sep 09 '14 at 11:27
  • 1
    @JonSkeet It's what I do, but considering seeing excessive use of explicit implementation at my new work, which really appals me, even the case of casting it to the interface to use a member, I looked around the internet for more info, found the codeproject page preaching explicit implementation as default with arguments like removing methods from an interface. Now, if you need inheritance, you have a protected virtual method that is being called in the explicit implementation, and you're back to square one, as the compiler doesn't tell you anything about that method. Thank you! – Alex Endris Sep 09 '14 at 13:48