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?