6

Ok, this arises from some discussion going on here.

Imagine the following scenario. Company Alpha publishes library Charlie which exposes among others, a type Charlie.Bar that explicilty implements the interface IFooable:

 public interface IFooable
 {
     void Foo();
 }

 namespace Charlie
 {
     public clas Bar: IFooable
     {
         void IFooable.Foo() {...}
         ....
     }
 }

Now it happens that company Beta is subclassing Charlie.Bar in its library Tango for some very particular functionality where the explicit implementation of IFooable.Foo doesn't cut it. Beta needs to "override" the interface implementation and achieve a seemingly equivalent virtual behavior; Calls to IFooable.Foo() should resolve correctly to the runtime type of the object. Note that having company Alpha modify the implementation of Charlie.Bar is not a viable option.

So how can this be done? Explicit interface methods are marked in CIL as virtual and final so you can not override them. Beta came up with this "hack":

using Charlie;

namespace Tango
{
     class Blah: Bar, IFooable
     {
         void IFooable.Foo() { //Bar specific implementation }
     }
}

Note the implementation of IFooable again in Blah even though it is redundant. With this code, you actually get the same behavior as a virtual method when calling IFooable.Foo():

 IFooable fooBar = new Bar();
 IFooable fooBlah = new Blah();

 fooBlah.Foo() // Blah's implementation is called.
 fooBar.Foo() // Bar's implementation is called.

Is this a very ugly hack? (I've seen it done in similarly justified? scenarios). What are the alternatives if any?

Community
  • 1
  • 1
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • 3
    `IFooable` is not redundant here. This is called interface re-implementation. My answer [here](http://stackoverflow.com/a/25008171/517852) has some explanation of this feature. One downside is that with interface re-implementation you don't get the ability to call the base implementation. – Mike Zboray Sep 09 '14 at 09:02
  • 1
    Does `Blah` *need* to be a subtype of `Bar`? If not, you could use composition: Store a reference to a `Bar` in your `Blah` class and forward all relevant calls to that. – Medo42 Sep 09 '14 at 09:05
  • Mikez is right. It is not redundant or hack. It is a [feature](http://msdn.microsoft.com/en-us/library/aa664594%28v=vs.71%29.aspx). – Sriram Sakthivel Sep 09 '14 at 09:06
  • The name of this in C# is [Interface re-implementation](http://msdn.microsoft.com/en-us/library/aa664594.aspx) (link is to old spec). You can do it for implicit (non-explicit) implentations as well. It is not a hack, but it is a bit of a smell in my opinion. ***Edit:*** I see that @SriramSakthivel linked the very same page while I was typing my comment! – Jeppe Stig Nielsen Sep 09 '14 at 09:07
  • This isn't really the designed for use case, I think. Although you could end up this exact situation if Bar had not included the interface in v1 and you wrote Blah with the interface and released. Then Bar v2 is released with the interface and you update your references. So, I think, it is there to accomodate this situation if it does arise, but I would be skeptical of a design to do this specifically ahead of time. – Mike Zboray Sep 09 '14 at 09:11

1 Answers1

-1

You're asking about opinions, right? I've been programming C# for 10 years. Yes, that does look like a hack. Not that ugly, but if I happened to have to write the Tango library I would try to isolate that code.

If I found interface re-implementation as solution to some design problem in my code-base where I control both Bar and Blah I would suggest that it is design over-complication.