For once and for all: class inheritance in C#

Methods of a class

The methods of a class are stored in a kind of table which maps the method signature to the method implementation. If you then call a method in your code, this table is consulted and the correct implementation of the method is called.
This is illustrated in the following figure:

classinheritancesuperclass

Derive class from another Base class

Deriving a class from another class makes the methods of the latter, the superclass class, available from instances of the former, the subclass. If you have no overlap in the signatures of the methods then nothing special happens. If you have methods in the both classes with the same signature, then without doing anything, you will get a compiler warning:

‘<subclass method signature>’ hides inherited member ‘<superclass method signature>’. Use the new keyword if hiding was intended.

If you want to compile without warnings, a good thing, you must preceed the method in the subclass with the ‘new’ keyword.

Thus in the superclass we have:

public string SomeClassMethod()

and in the subclass we have:

new public string SomeClassMethod()

The result of hiding a member is that when we have a class of the instance of the subclass and cast it to an instance of the superclass, then the method of the superclass is called:

ClassFromClassDefinition inherited = new ClassFromClassDefinition();
ClassDefinition inheritedAsParent = inherited;

Assert.AreEqual(ClassFromClassDefinition.ClassFromClassDefinitionSomeClassMethodReturnValue, inherited.SomeClassMethod());
Assert.AreNotEqual(ClassDefinition.SomeClassMethodReturnValue, inherited.SomeClassMethod());
Assert.AreEqual(ClassDefinition.SomeClassMethodReturnValue, inheritedAsParent.SomeClassMethod());

What happens is illustrated in the following image:

classinheritancevirtualnew

When deriving from a superclass, the methodtable of this superclass (ClassDefinition) is integrated in the methodtable of the subclass (ClassFromClassDefinition). As you can see from the SomeMethod table entries you now have two entries for them: one for the superclass methodtable and one for the subclass methodtable.

If you access an object of the type of the subclass from an instance of this subclass, you use the methodtable for the subclass. If however you cast to the superclass, then the methodtable you use is the one for the superclass and calling SomeMethod results in calling the superclass version of this method. Something which isconfirmed by the above assertions.

If you don’t want this behaviour but instead want the subclass method to be called from superclasses casted from the subclass, you must use the ‘virtual’ and ‘override’ keywords

Thus in the superclass we have:

virtual public string VirtualMethod()

and in the subclass we have:

override public string VirtualMethod()

which results in the desired behaviour:

ClassFromClassDefinition inherited = new ClassFromClassDefinition();
ClassDefinition inheritedAsParent = inherited;
 
Assert.AreEqual(ClassFromClassDefinition.ClassFromClassDefinitionVirtualMethodReturnValue, subclass.VirtualMethod());
Assert.AreEqual(ClassFromClassDefinition.ClassFromClassDefinitionVirtualMethodReturnValue, subclassAsSuper.VirtualMethod());

This is illustrated by following picture:

classinheritancevirtualoverride1

Now, don’t be fooled in thinking the ‘virtual’ keyword resulted in the above behaviour. It is actually a cooperation of the ‘virtual’ and ‘override’ keywords.
If you replace the ‘override’ keyword with the ‘new’ keyword you get the old behaviour of hiding and casting to the supertype will reveale the hidden supertype member.
Thus ‘virtual’ creates the opportunity for users of your class to use overriding or hiding behaviour by choosing the either the ‘new’ or ‘override’ keyword.

However, what happens when using ‘third generation’ inheritance, thus:

public class ClassDefinition
public class ClassFromClassDefinition : ClassDefinition
public class ThirdGenerationClass : ClassFromClassDefinition

There are a few combinations possible here which I will not all explain in this article.
You can download the associated code which provides sample implementations of the combinatons and assertions to see what happens.

The general conclusion we can make is the following:
The ‘virtual’ keyword marks a method as being a candidate for overriding and is generally used in the superclass
The ‘overriding’ keyword marks a method as overriding and is generally used in the subclass
The ‘new’ keyword marks a method as hiding the superclass member
The combination of the ‘new’ and ‘virtual’ keywords in the middle of an inheritance tree marks a method as hiding the implementation of all classes below and make the method a candidate for overriding for all classes above this class in the inheritance tree

Download

You can download the sample code here. To run it you will need MbUnit because that is used to make the assertions. However, just studying the code will also get you a long way. Enjoy…

Links

Superclass (computer science)
Subclass (computer science)
Virtual method table

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s