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?
Remember Me
Page rendered at Monday, September 08, 2008 5:15:38 AM (Cen. Australia Standard Time, UTC+09:30)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.