Implicit Vs. Explicit Interface Method Implementation
In the NORMA project we were encouraged to use Explicit Interface Method Implementation (EIMI). However, after reading a bit of Jeffrey Richter’s CLR via C#, I’ve decided to change the way I implement interfaces.
This entry is also a response to Ben’s blog entry, located here, which you should read first because it explains the difference between the two approaches.
Now…a little about why I disagree that EIMI should be used as often as possible.
- Having to cast an object to the interface just to call the interface method can get a little annoying in code. When you’re working on a team that might not be so familiar with this pattern then it takes extra time for them to get acquainted with it, because it’s a little awkward. However, this may be a superficial reason to some, so let’s continue…
- Regarding that cast, think about a case where you have a value type that has used EIMI to implement an interface. When you cast to the interface you burden your application by forcing a box operation on the value type so it can actually be treated as that interface type.
- Furthermore, with EIMI, if you derive from a class that implements an interface in this manner, you can’t call your base class’s implementation of that interface.
Now, I’m not saying that EIMI is useless. There are some specific cases when it is necessary. Take for instance the following example:
[code lang="csharp"] public interface IWindow
{
object GetMenu();
}
public interface IRestaurant
{
object GetMenu();
}
public class Pizzeria : IWindow, IRestaurant
{
object IWindow.GetMenu() { … }
object IRestaurant.GetMenu() { … }
}
[/code]
Here you have to use EIMI because you have two interfaces with the same method names. It doesn’t make sense to call GetMenu() and expect the CLR to infer which interface you’re binding to.
Another case where EIMI can come in handy is to improve compile-time safety. Let’s say you have a struct that implements a non-generic interface, like IComparable:
[code lang="csharp"] public interface IComparable
{
Int32 CompareTo(Object other);
}
public struct SomeValueType : IComparable
{
private int x;
public SomeValueType(Int32 x) { this.x = x; }
public Int32 CompareTo(Object other)
{
return x - ((SomeValueType)other).x;
}
}
// Now in some other method I can call CompareTo like this
public static void Main()
{
SomeValueType v = new SomeValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); // Undesired Boxing
n = v.CompareTo(o); // InvalidCastException
}[/code]
So now instead of what’s listed above, you want to enforce some semblance of compile-time safety with your interface method. Here’s something you can do with EIMI:
[code lang="csharp"] public struct SomeValueType : IComparable
{
private int x;
public SomeValueType(Int32 x) { this.x = x; }
Int32 IComparable.CompareTo(Object other)
{
return CompareTo((SomeValueType)other);
}
public Int32 CompareTo(SomeValueType other)
{
return x - other.x;
}
}
// Now in some other method I can call CompareTo like this
public static void Main()
{
SomeValueType v = new SomeValueType(0);
Object o = new Object();
Int32 n = v.CompareTo(v); // No Boxing
n = v.CompareTo(o); // Compile-time Error
}[/code]
Of course, if we box SomeValueType into an IComparable instance then it would throw as above, so this s”olution” only alleviates the problem; in most cases your best bet would be to use a generic interface to enforce type-safety and remove boxing/unboxing operations.
Because of this, I have concluded that I will not use EIMI every chance I get, but instead will focus on using IIMI unless I really need to use EIMI as outlined by cases above.
Syndication
June 7th, 2007 at 10:12 am
I find 1 & 3 of your reasons for not using explicit interfaces somewhat minor; although, your 2nd point of having to box value types has its merit. But doesn’t that only really come into the equation when performance is an issue?
June 7th, 2007 at 10:28 am
I think it’s always an issue of contention, regardless of whether performance is an issue. I would think, though, that we should always write code with performance in mind.
Although since this blog I have learned that Matt Curland has some other reasons for using EIMI…which I hope to get out of him before I leave.
July 26th, 2007 at 3:04 pm
Have you gotten these reasons out of him yet?
July 27th, 2007 at 5:52 am
No, unfortunately. Other things have been taking a priority recently, but one comment of his made sense in context–that VB programmers are likely to use explicit implementation whereas those who came from C and C++ are likely to use implicit.
I think the reason stems from the fact that VB (even VB.NET) requires that when you write a method that implements an interface, you must explicitly write what interface method it implements (e.g. Implements IDisposable.Dispose).
But I’ll track him down sooner or later…