Once again, in this series of posts I look at the parts of the .NET Framework that may seem trivial, but can help improve your code by making it easier to write and maintain. The index of all my past little wonders posts can be found here.
Most of the time in C#, we implement interfaces implicitly. This is by far the simplest method and makes the method available both to consumers of the interface and the implementing type directly.
There are times, though, when you may want to implement an interface, but hide or change how the interface implementation is exposed in the implementing type. This is done through explicit interface implementation, which we will discuss today.
Implicit Interface Implementation
Implementing interfaces in C# is easy, we simply have our implementing type satisfy the interface by having it contain a member which satisfies the interface (or can be abstract of course). The easiest way to do this is with implicit implementation.
So, for example, say we have a sample interface (yes, I could make it a generic, but bear with me for now):
1 : public interface IFactory
2 : {
3 : object Create();
4:
}
We can implicitly implement this interface by creating a type that has a method with the same signature and return type:
1 : public class SentenceBuilder : IFactory 2 : {
3 : // ...
4 : 5
: // Because this method has the same signature and return type, it
6 : // is considered an implicit interface implementation
7 : public object Create() 8 : {
9 : return “Both class and interface see
this.”;
10:
}
11:
}
When we do this, we call the same method whether we call the method from an instance of IFactory or SentenceBuilder:
1 : // same object, one as SentenceBuilder, one as Factory
2 : var builder = new SentenceBuilder();
3 : 4 : IFactory factory = builder;
5 : 6 : // result will be the same regardless of the reference we call from
7 : Console.WriteLine(factory.Create());
8 : Console.WriteLine(builder.Create());
Many times, this is sufficient for our needs. But sometimes, we’d like a little bit more control of how a type implements an interface while still being required to satisfy the interface contract. This is where explicit interface implementation comes into play.
Explicit interface implementation – to hide interface member in implementing type
To implement an interface explicitly, you drop the public access specifier (all interface members are public), and predicate the method name with the interface name and dot as follows:
1 : public class HiddenSentenceBuilder : IFactory 2 : {
3 : // ...
4 : 5
: // Notice no access specifier and interface name prefix of method name
6 : object IFactory.Create() 7 : {
8 : return “Only IFactory will see this.”;
9:
}
10:
}
Now, if we try to use this in the same way as the implicit example, we will see something curious:
1 : // same object, one as HiddenSentenceBuilder, one as Factory
2 : var builder = new HiddenSentenceBuilder();
3 : IFactory factory = builder;
4 : 5 : // This works, because Create() is part of IFactory's public interface.
6 : Console.WriteLine(factory.Create());
7 : 8
: // Compiler error, Create() is a private part of HiddenSentenceBuilder's
9 : // interface because it was explicitly implemented.
10 : Console.WriteLine(builder.Create());
This is interesting and brings us to one of the first uses that we can use explicit interface implementation for: hiding an interface implementation from the implementing type. This can be useful if you need to satisfy a legacy interface, but really don’t like the way it is implemented and prefer to hide it from the common use-case scenario of calling from the class directly.
Explicit interface implementation – to implement member differently depending on usage
Another thing you can use explicit interface implementation for is satisfying an interface, but giving a different implementation if called from the implementing type directly. For example, our IFactory (by our design) returns object. But we could opt to have our OverloadedSentenceBuilder below implement it to return a string instead.
However, we can’t do this with implicit interface implementation:
1 : // Bad example, won't compile!!!
2 : public class OverloadedSentenceBuilder : IFactory 3 : {
4 : // ...
5 : 6 : public object Create() 7 : {
8 : return “Satisfy IFactory.”;
9:
}
10 : 11 : // Won’t compile, overloads can’t differ by return type
12 : public string Create() 13 : {
14 : return “Direct from implementing type.”;
15:
}
16:
}
This won’t even compile, because overloads cannot differ by only a return type. However, with explicit interface implementation, we can do this because the interface method is hidden when using the implementing type directly, so there is no conflict:
1 : // This will compile!
2 : public OverloadedSentenceBuilder : IFactory 3 : {
4 : // ...
5 : 6 : // We get this if called from IFactory reference
7 : object IFactory.Create() 8 : {
9 : return “Satisfy IFactory.”;
10:
}
11 : 12 : // We get this if called from OverloadedSentenceBuilder reference
13 : public string Create() 14 : {
15 : return “Nicer!No objects.”;
16:
}
17:
}
Now, when we call our methods again, we will call a different method depending on which reference we call through. Notice that the method used is chosen at compile time! This is not an override, it is a form of overloading.
1 : // same object, one as OverloadedSentenceBuilder, one as Factory
2 : var builder = new OverloadedSentenceBuilder();
3 : IFactory factory = builder;
4 : 5 : // Calls IFactory.Create() since called through an IFactory reference
6 : Console.WriteLine(factory.Create());
7 : 8 : // Calls OverloadedSentenceBuilder’s Create() since called through an
// OverloadedSentenceBuilder
9 : Console.WriteLine(builder.Create());
So, as you can see, we can use explicit interface implementation when we want to have a different implementation when we are called directly from the class, or from the interface – or when we want to change the return type from interface’s signature.
Explicit Interface Implementation – Resolving interfaces that collide
Now, if the two examples above seem to be a rare or uninteresting use case to you, consider this case which happens far more likely: implementing two interfaces that collide. That is, the two interfaces may have members with the same name that are incompatible (or that we want to implement differently).
For example, what if we did have both IFactory and IFactory<T> interfaces? Perhaps IFactory was legacy before generics, or perhaps we like having plain old IFactory around for being able to collect together a group of factories regardless of what they return. In either case, let’s assume we have:
1 : // "Legacy" form that returns as object
2 : public interface IFactory
3 : {
4 : object Create();
5:
}
6 : 7 : // Generic form that returns as generic type parameter T
8 : public interface IFactory<T> 9 : {
10 : T Create();
11:
}
Now let’s say we wanted to implement them both. Often times with collections we will do something similar by implementing both IEnumerable and IEnumerable<T>. However, we can’t implicitly satisfy both interfaces because of the same issues when we tried to overload it before:
1 : public class DoubleSentenceBuilder : IFactory, IFactory<string> 2 : {
3 : // ...
4 : 5 : // To satisfy IFactory
6 : public object Create() 7 : {
8 : return “Satisfy IFactory.”;
9:
}
10 : 11 : // To satisfy IFactory<T>, BUT won’t compile!
12 : // Overloads can’t differ by return type only.
13 : public string Create() 14 : {
15 : return “Nicer!No objects.”;
16:
}
17:
}
So, once again, explicit interface implementation to the rescue!
1 : public class DoubleSentenceBuilder : IFactory, IFactory<string> 2 : {
3 : // ...
4 : 5 : // Explicitly implement IFactory’s Create(), this will ONLY
6 : // be visible from an IFactory reference.
7 : object IFactory.Create() 8 : {
9 : return “Satisfy IFactory.”;
10:
}
11 : 12 : // Implicitly implement IFactory<string>’s Create(), this will be
13
: // visible through both DoubleSentenceBuilder and IFactory<string>.
14 : public string Create() 15 : {
16 : return “Satisfy IFactory<string>.”;
17:
}
18:
}
Again, calling them both:
1 : // same object, one as DoubleSentenceBuilder, one as Factory
2 : var builder = new DoubleSentenceBuilder();
3 : IFactory factory = builder;
4 : 5 : // calls IFactory.Create() since called through IFactory reference
6 : object result2 = factory.Create();
7 : 8 : // calls IFactory<string>’s Create() since called through
// DoubleSentenceBuilder
9 : Console.WriteLine(builder.Create());
Notice that we let the more specific interface be our implementing type implicit implementation, though we didn’t have to have it this way. We could have made IFactory the implicit and IFactory<string> the explicit, or even made both explicit and hide Create() in the implementing type, or get really crazy and have explicit implementations for both and a third implementation when called from the implementing type. I think you get the point, there’s a lot of power here!
Summary
Explicit interface implementation is a handy technique for changing the way an interface implementation appears in the implementing type. You can use it to hide the interface method in the implementing type, resolve conflicting overloads with the implementing type, give different implementations between the interface(s) and/or implementing type, etc.
Technorati Tags: C#,CSharp,.NET,Little Wonders,interface,explicit interface implementation