Fine-tuning polymorphism in C# using the new keyword

This doesn’t come up too often but can be useful. Sometimes, when using inheritance, it can be difficult to get the right implementation of a virtual method called. This is the kind of model I had today:

namespace InheritanceTest
{

	public class BaseClass
	{
		public BaseClass() {}

		public virtual void A(int count)
		{
			for (int i = 0; i < count; i++)
				B(string.Format("{0} Base Hello", i));	// This calls DerivedClass.B(string)
		}

		public virtual void B(string s)
		{
			Console.WriteLine("Base: "+s);
		}
	}

	public class DerivedClass : BaseClass
	{
		public DerivedClass() : base() {}

		public override void A(int count)
		{
			base.A(count);	// call BaseClass.A(int)
		}

		public override void B(string s)
		{
			Console.WriteLine("Derived: "+s);
		}
	}

	class MainClass
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("Test begins:");

			DerivedClass obj = new DerivedClass();
			//obj.B(10);

			Console.WriteLine("Test ends.");
		}
	}
}

When this is compiled and run, the method called in BaseClass.A() is DerivedClass’s implementation of B(). The series of method calls will look like this:

  1. DerivedClass.A()
  2. BaseClass.A()
  3. DerivedClass.B() ten times

So when BaseClass.A() makes the call to B(), the derived class’s B() method is found and executed, rather than BaseClass.B(). This is exactly how you would usually want the inheritance to work; the derived class has methods that override the base class, and the base class calls fall through to the child’s implementation of the virtual methods.

The problem with this is if you want to be able to use the base class’s implementation of B() in BaseClass.A()’s call to B(). BaseClass.B()’s implementation may contain code required in BaseClass, but DerivedClass.B()’s implementation is not appropriate for use in BaseClass. Basically you want the following series of method calls:

  1. DerivedClass.A()
  2. BaseClass.A()
  3. BaseClass.B() ten times

We need to indicate to the compiler that, although DerivedClass.B() implements B(), it doesn’t necessarily override BaseClass’s implementation of B(). That is done by changing the override keyword in DerivedClass.B()’s declaration to new:

Change:
   public override void B(string s)
to:
   public new void B(string s)

The effect of this is that when B() is called in BaseClass, it will be BaseClass.B() that will be executed, because DerivedClass.B() is flagged as a new implementation of the B() method that does not override the existing one. The new DerivedClass.B() method is still visible in DerivedClass and beyond:

DerivedClass obj = new DerivedClass();
obj.B("Test");   // This will execute DerivedClass.B(), not BaseClass.B()

will execute DerivedClass.B().

Leave a Reply