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 (9)

  1. Roy J. Salisbury @ VsDevCentral says:

    Not sure what your trying to accomplish, but I prefer this:

    // explicit

    void I.F() {

    F();

    }

    // actual

    public void F() {

    }

    This allows me to do things like:

    public abstract class MyClass : IMyInterface {

    void IMyInterface.MyMethod() {

    MyMethod();

    }

    public abstract void MyMethod();

    }

    This way, my contract is valid, and I can still use abstract methods in the base class.

  2. 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(); }

    }

    }

  3. 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.

  4. jaybaz [MS] says:

    "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

  5. AndrewSeven says:

    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.

  6. 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?