Interface implementation & casts.
Interface implementation & casts.
I’ve previously blogged about this unusual habit when implementing an interface:
Use explicit interface implementation.
interface I
{
void F();
}
class C : I
{
void I.F()
{
//...
}
}
I prefer my code to say “Here is where I satisfy the interface’s requirement that I implement method F()”. Otherwise you may think the method is there on its own merit.
The annoying thing about this approach is that it occasionally requires casts. If I have a ‘C’ and I want to call ‘F’ I have to cast. The cast is quite ugly. (Does it also have a perf impact?)
Here’s one way to deal with the problem:
class C : I
{
public I I { get { return this; } }
void I.F()
{
//...
}
}
// usage:
C c = ...;
c.I.F();
Don’t read this as “get the ‘I’ property from ‘c’ and call ‘F()’ on it.”
Read this as “call ‘I.F()’ on ‘c’.” Suddenly it makes perfect sense. The method I wrote was called “I.F()” so the method I call should be “I.F()”.
But there’s a catch. What do I do if the interface is generic?
interface I<T>
{
void F();
}
class C<T> : I<T>
{
// what's the right name for this property?
public I<T> I { get { return this; } }
void I<T>.F()
{
//...
}
}
You can’t have generic properties in C#.
I think I will call the property “I_T”. It’s not ideal, but I think I’ll cope.
Got any ideas about how to improve this further?
Comments
- Anonymous
June 18, 2004
The comment has been removed - Anonymous
June 18, 2004
I think you example would have been okay. I think it's just that you can't have a property which introduces a new type parameter, so you can't have:
class C<T>
{
U Property<U> where U: new
{
get { return new U(); }
}
}
but you could do:
class C<T> where T: ew
{
T Property<T>
{
get { return new T(); }
}
} - Anonymous
June 18, 2004
I usually implement my interfaces like that only when I don't want the type to expose that behaviour, but only when polymorphed to the interface type.
I just think you're over-doing it a bit. - Anonymous
June 19, 2004
"I just think you're over-doing it a bit."
Yeah, that's the point!
http://blogs.msdn.com/jaybaz_ms/archive/2004/06/13/154918.aspx - Anonymous
June 21, 2004
I think this is a beautiful technique.
I spent several hours playing with it over the weekend and will surely use it in the future.
Often when I am implementing an interface, I am expecting the class to almost always be cast as the interface when used.
I did some experiments using an inner DirectCastClass and a DirectCast property on the object. Passing my class to the DirectCastClass constructor let me use the same trick to not cast.
As I played with it, I got to the point where I think it might be nice to somehow do this with attributes. To use an attribute to specify which base classes and interfaces whould be directly exposed.
[ExposeDirectCast(typeof(I))]
class C : I
{
void I.F()
{
}
}
Then be able to do.
C.DirectCast.I.F();
or maybe
C.I.F();// but this might lead to confusion as to what I is. - Anonymous
June 21, 2004
What you are trying to do will not work in general....
The following code is legal C#
public class C : I {
private I i_;
public void I.F() {
}
public I I {
get {
reutrn i_;
}
}
}
However, your extension will introduce an ambiguity. Does the statement c.I.F() mean run the method I.F() on object c or run the method F on the object c.I?