defaultforvisualstudioimplementationofinterfaces

Cancel Edit [WikiEntry.PreviewButtonText] Save
My original blog post is here


I've recently been wondering why Microsoft, in their infinite wisdom, has decided to provide helper code in both C# & VB.Net that promotes bad OOP coding.

Have you ever implemented an interface in either language?

Well, Visual Studio - in 2002, 2003 & Whidbey - auto-creates the implementation signatures in both languages and marks them "Public". I'm sure you know that.

Now this is a big problem in both C# & VB.Net. Let's see why in C# first.

If I write this code:

		      class Module
		      {
		            [STAThread]
		            static void Main(string[] args)
		            {
		                  ClassY InstanceY = new ClassY();
		                  [((IFoo)InstanceY).DoMethod();]
		                  [((IBar)InstanceY).DoMethod();]
		                  [InstanceY.DoMethod();]
		                  [Console.ReadLine();]
		            }
		      }
	

		      public interface [IFoo] {void DoMethod();}
		      public interface [IBar] {void DoMethod();}
	

		      public class ClassX : [IFoo]   
		      {
		            public void [DoMethod()] {Console.WriteLine("IFoo.DoMethod");}
		      }
	

		      public class ClassY : ClassX, [IBar]
		      {
		            public void [DoMethod()] {Console.WriteLine("IBar.DoMethod");}
		      }
	

Visual Studio complains with "The keyword new is required on 'ConsoleApplicationCSharp.ClassY.DoMethod()' because it hides inherited member 'ConsoleApplicationCSharp.ClassX.DoMethod()'".

So I insert "new" on "DoMethod()" in "ClassY", like this:

		      public class ClassY : ClassX, [IBar]
		      {
		            public new void [DoMethod()] {Console.WriteLine("IBar.DoMethod");}
		      }
	

My output becomes:

		 [IFoo.DoMethod]
		 [IBar.DoMethod]
		 [IBar.DoMethod]
	

Pretty much what I should expect, but I'm a conscientious programmer so I want to avoid "new" (or "shadows" in VB.Net) so I mark the "ClassY" method as "private" rather than "public", like so:

		      public class ClassY : ClassX, [IBar]
		      {
		            private new void [DoMethod()] {Console.WriteLine("IBar.DoMethod");}
		      }
	

The output now becomes:

		 [IFoo.DoMethod]
		 [IFoo.DoMethod]
		 [IFoo.DoMethod]
	

When I explicitly call the "IBar" interface method it calls the method of the class that doesn't even implement the interface. That's crazy!

So, to avoid the problem I declare the implementation explicitly:

		      public class ClassX : [IFoo]   
		      {
		            void [IFoo.DoMethod()] {Console.WriteLine("IFoo.DoMethod");}
		      }
	

		      public class ClassY : ClassX, [IBar]
		      {
		            void [IBar.DoMethod()] {Console.WriteLine("IBar.DoMethod");}
		      }
	

Now, of course, the code that calls the "DoMethod()" on the native "InstanceY" object can't see either method. But isn't that what we really would want to do? It avoids any ambiguity.

Let's look at a similar thing in VB.Net. My code is now this:

		    Module Main
		        Sub Main()
		            Dim InstanceY As New ClassY
		            [CType(InstanceY,] [IBar).DoBar()]
		            [CType(InstanceY,] [IFoo).DoFoo()]
		            [InstanceY.DoBar()]
		            [InstanceY.DoFoo()]
		            [Console.ReadLine()]
		        End Sub
		    End Module
	

		    Public Interface [IFoo]
		        Sub [DoFoo()]
		    End Interface
	

		    Public Interface [IBar]
		        Sub [DoBar()]
		    End Interface
	

		    Public Class ClassX
		        Implements [IFoo]
		        Public Sub [DoBar()] Implements [IFoo.DoFoo]
		            Console.WriteLine("IFoo.DoFoo")
		        End Sub
		    End Class
	

		    Public Class ClassY
		        Inherits ClassX
		        Implements [IBar]
		        Public Sub [DoFoo()] Implements [IBar.DoBar]
		            Console.WriteLine("IBar.DoBar")
		        End Sub
		    End Class
	

Notice that since I'm being a nasty programmer I've swapped the Names of the method implementations. Think of it like replacing "Save" with "Delete".

Now of course, what happens? My dear user runs this code and gets the following:

		 [IFoo.DoFoo]
		 [IBar.DoBar]
		 [IBar.DoBar]
		 [IFoo.DoFoo]
	

Again, the answer is to explicitly declare both implementations "Private". It avoids any ambiguity.

But the answer is not to enforce the use of "Private". Apart from the times when "Protected" is needed, there may well be a need for the developer to make an implementation of an interface "Public" or "Friend".

So, my open question, why has Microsoft made "Public" the default for implementation of interfaces?
Microsoft Communities