Shadowing vs Hiding vs Overriding

In C#, it is easy to confuse hiding with overriding. Both are ways to change the implementation of elements from a base class. But there are some significant differences between the two.

A further confusion steps in with the term shadowing. Shadowing is a VB concept. In C#, this concept is called hiding, though there is a subtle difference between these two terms.

  1. For VB.NET, shadowing is element name dependent, and hides ALL the elements in the base class regardless of signature. So a base class with an element called “Hello()” with ten different signatures would all be shadowed by a derived class.
  2. For C#.NET, hiding is signature dependent. So the new keyword would only be applied to the specific element with the same signature. In this case, only the particular “Hello()” element with exactly the same signature would be hidden, and the remaining nine “Hello()”s would not be affected.

Hence, we use both shadowing and hiding to provide new implementations to the base class without overriding it. That is, the access level, return type, and the signature of the derived class elements which are shadowed, may differ from the base class. However, when hiding in C#, the access level, the signature, return type of the derived class must be same as the base class. Otherwise, there’s nothing to hide.

Now, back to the technical differences between hiding and overriding.

(1) New is reference-type specific, overriding is object-type specific.

In simple terms, hiding allows you to implement the “reference signature” in a new manner, and keeps the original implementation (ie. two versions of the same signature can be accessed from outside classes). Overriding on the other hand, rewrites the “reference signature” (ie. only one version of the signature can be accessed from outside classes). However, two signatures are physically present in memory for both overriding and hiding.

Hence, if base.Hello() is overridden by child.Hello(), then only child.Hello() is seen by outside classes. Using new however, allows both base.Hello() and child.Hello() to be viewed by outside classes, depending on the run-time typecast. Below is a code example of what I meant.

The illustrated code can be downloaded here [code demo].

First, we implement the base class “Foo”, and “Bar” is the derived class. “Xnew” represents the hidden property, whereas “Xovr” represents the overridden property. In addition, “BaseXnew” and “BaseXovr” represent the physical references to the properties in the “Foo” parent class. An instance “bar” is created from the derived class and its properties are printed out in the console.

Here, you can see that when bar is of type “Bar”, the child implementations are used for both overriding and hiding. However, when bar is type-casted to its parent class “Foo”, the parent implementation that was originally hidden by the new keyword is now used. On the other hand, override still uses the child implementation.

(2) The parent class is ignorant of what is new

With new, the parent class cannot enforce or prohibit hiding. Basically, it assumes no knowledge that its children will try to replace some of its parts. So there is no need to pre-declare virtual in the parent to implement a new method. However, to override a base class element, the parent class must self-declare that element as overridable to avoid its children from replacing its significant parts.

As such, the new keyword allows for changes in the access level of the element. So if the base element was “internal”, then the new element can use any other access levels. Overriding however is access level specific because the parent knows the parts that could get replaced.

Knowing the above differences should be enough to get you started. More details can be found at http://msdn.microsoft.com/en-us/library/ms172785%28VS.80%29.aspx

  1 comment for “Shadowing vs Hiding vs Overriding

  1. Atithi
    April 16, 2013 at 9:51 am

    Very helpful post to understand the difference !

Leave a Reply

Your email address will not be published. Required fields are marked *