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?