Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
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?