Monday, July 7, 2008

Method Hiding - Feature or Bug in Compiler?

Since its very beginning C# has a 'method hiding' feature, which lets us 'hide' base class non-virtual methods. In other words one can write:
class Base
{
public void Test() {
Console.WriteLine("Base");
}
}

class Derived : Base
{
public new void Test() {
Console.WriteLine("Derived");
}
}

//...

Derived d = new Derived();
d.Test(); // "Derived" is printed


So far so good, but what happens if I write:



Base d = new Derived();
d.Test(); // "Base" is printed


Is this an intended behavior? Well, may be yes, but may be no. In case of 'no', we just called a wrong function, and no warning or error was issued by the compiler... Just consider again what happened, we declared a non-virtual method - that's our contract that should be ensured by the compiler. Instead it provides us with a feature to break it.



That's not all, consider the situation where you have some 3rd party library and use it in your project. Now the vendor releases a new version where he hides some method and provides an alternative implementation. Your program will still call the old method until you recompile! So in case you have several modules some recompiled and some not, you may have inconsistent behavior...



Of course you can always find use-cases, where the feature is carefully used and actually is very useful in that context. Yet its disadvantages outweight the advantages, so I think it would be better if we will develop our programs without using it.



Unfortunately there is an additional very similar "feature" - private interfaces, which can be implemented by a type even if its base class already implemented it and declared it sealed. Again the language helps us to break the contract and if it's not done carefully enough, the bugs won't wait to come...

No comments: