Ross Coded Classes

Programming tips with no rose colored glasses.

A Hazard of Reimplementing an Explicit Interface

When implementing an interface explicitly, it is best to create virtual methods or properties if you ever expect a subclass to need to change the behavior.  Implementing the interface explicitly helps to not pollute the public members of a type, but subclasses cannot reach the superclass’s implementation if they have to reimplement the interface to change the behavior.  Exposing protected methods for the explicitly implemented members would keep the public interface clean while still allowing access by subclasses.
 
Somewhere I read a post from one of the .NET Framework developers that confirmed the superclass’s implementation would be unreachable in situations such as the one below.  You can find more on Google: http://groups.google.com/groups/search?hl=en&q=explicit+interface+base+c%23 

// Reimplementation of explicit interface implementation makes
// superclass implementation inaccessable from subclass.
 
internal class Program
{
      private static void Main()
      {
            I i = new B();
            System.Console.WriteLine(i.Stuff());
            i = new C();
            System.Console.WriteLine(i.Stuff());
      }
}
 
internal interface I
{
      int Stuff();
}
 
internal class A : I
{
      protected int count = 0;
 
      int I.Stuff()
      {
            return 1;
      }
}
 
/// <summary>
/// Normal code can't get there.
/// </summary>
internal class B : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            // Doesn't compile, not allowed to use "base" here.
            // return 2 + ((I)base).Stuff();
 
            return 2 + ((I) ((A) this)).Stuff();
      }
}
 
/// <summary>
/// Even Reflection can't get there.
/// </summary>
internal class C : A, I
{
      int I.Stuff()
      {
            count++;
            if (count > 100)
            {
                  System.Console.WriteLine("Infinite loop");
                  return -1;
            }
 
            System.Reflection.MethodInfo stuffMethodOfI;
            stuffMethodOfI = typeof (A).GetInterface("I").GetMethod("Stuff");
            return 2 + (int) stuffMethodOfI.Invoke((A) this, null);
      }
} 

 Output: 


Infinite loop
199
Infinite loop
199 

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.