Chapter 2 -Interface in c#-----Explicit Interface Implementation

If a class implements two interfaces that contain a member with the same signature, then implementing that member on the class will cause both interfaces to use that member as their implementation. For example:


What are good reasons to use explicit interface implementation for the sole purpose of hiding members?

Explicit Interface Implementations in C#

June 25, 2008
Well, you learn something new every day. Although explicit interface implementations are fairly common when you are implementing two interfaces with conflicting (ie, the same) member signatures, they can also be used to “hide” a interface member.
While working with the RegistryKey class today, I noticed that even though it implements IDisposable, it does not publicly expose Dispose(). Read on to find out why.

We start with a general discussion of explicit interface implementations. Suppose you have the following two interfaces:
  1. interface Foo {   
  2.     void Hello();   
  3. }   
  4. interface Bar {   
  5.     void Hello();   
  6. }  
Then, in the following class, both Foo.Hello and Bar.Hello will call this classes implementation of Hello:
  1. class Baz : Foo, Bar {   
  2.     public void Hello() {   
  3.         /* do something here. */  
  4.     }   
  5. }  
And of course, if we wanted separate implementations for Foo.Hello and Bar.Hello we would do:
  1. class Baz : Foo, Bar {   
  2.     void Foo.Hello() {   
  3.         /* do something here. Called by Foo.Hello */  
  4.     }   
  5.     void Bar.Hello() {   
  6.         /* do something here. Called by Bar.Hello */  
  7.     }   
  8. }  
Now, notice that the public access modifier is no longer present. Try putting the public access modifer in, and you’ll get an error: The modifier ‘public’ is not valid for this item. This is because if Baz exposed Hello publicly, it wouldn’t be clear which Hello was to be called. And indeed, you can’t simply call Hello() on an instance of Baz, you have to cast it to Foo or Bar first:
  1. void SomeFunction() {   
  2.     Baz b = new Baz();   
  3.     b.Hello(); /* ERROR: will not compile */  
  4.     ((Foo)b).Hello(); /* Calls Foo.Hello */  
  5.     ((Bar)b).Hello(); /* Calls Bar.Hello */  
  6. }  
OK, so this is all pretty basic and most C# developers will be aware of all this. Most people will have stumbled across it by necessity.
So now I look at the lesser known property of explicit interface implementations: used to “hide” interface implementations that aren’t in conflict.
You may be surprised to know that if you remove the inheritance from, say, Bar in the above class, the thing will still compile:
  1. class Baz : Foo {   
  2.     void Foo.Hello() {   
  3.         /* do something here. Called by Foo.Hello */  
  4.     }   
  5. }  
Moreover, when you try to do something like this:
  1. void SomeFunction() {   
  2.     Baz b = new Baz();   
  3.     b.Hello(); /* ERROR: will not compile */  
  4. }  
You’ll receive an error: “‘Baz’ does not contain a definition for ‘Hello’”. You’ll notice that we don’t provide the public access modifier to Foo.Hello in our Baz class, so of course we get such an error. So it turns out that you can essentially hide interface members of a class. From the Implementing Interface Members Explicitly documentation on MSDN:
When an interface member is explicitly implemented by a class, the member can be accessed only by using a reference to the interface. This has the effect of hiding the interface member
It turns out that this is what RegistryKey() does with IDisposable.Dispose(). Dispose() is hidden by using explicit interface implementations. So you can do the following:
  1. void SomeFunction(RegistryKey key) {   
  2.     ((IDisposable)key).Dispose();   
  3. }  
But not:
  1. void SomeFunction(RegistryKey key) {   
  2.     key.Dispose();   
  3. }  
So why would you want to do this? Well, the documentation cited before also states:
Consider implementing interface members explicitly to hide a member and add an equivalent member with a better name.
This effectively renames a member. For example, Stream implements Dispose explicitly and provides the Close method in its place.
I guess this was the intention with RegistryKey. It seems to me, however, that this reasoning is a bit silly. Dispose, according to MSDN, “performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.” Isn’t this what we want to happen when we are done with a RegistryKey instance? I would suggest that the member with the “better name” here is Dispose, not close. If we’re working in the .NET paradigm, we should stick to Dispose. Many classes could then avoid the need to have Close() at all, and ensure that novice .NET developers are exposed to IDisposable more often. Alas, it is not the case.

Comments