Some polymorphism in C#

I was watching an online C# 6 course by Jesse Liberty and then decided to play a little bit with inheritance, polymorphism, and method binding. The result of that was a Gist that you can see below.

 

Essentially, C# works pretty much like C++ in the sense it supports both static and dynamic binding, but C# forces the programmer to be more explicit:

 

  • When hiding a method from a subclass, which we could refer to as overriding with static binding, we will get a compiler warning unless we make the method hiding explicit with new:

Warning CS0108: 'B.Foo()' hides inherited member 'A.Foo()'. Use the new keyword if hiding was intended. (CS0108)

 

  • When overriding a method from a subclass, which we could refer to as overriding with dynamic binding, the first requisite is having the base method declared as virtual (otherwise, there will be a compiler error). Apart from this, we will get another warning unless we make the overriding explicit with override:

Warning CS0114: 'B.Foo()' hides inherited member 'A.Foo()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword. (CS0114)

This basically means that binding will always be static unless we tell the compiler we want to make it dynamic with override. This is an important difference with C++, as in C++ once a base method has been declared as virtual, it will always be dynamically bound.

 

Take a look at the Gist with the examples here:


using System;
namespace PolymorphismDemo
{
public class A
{
public virtual void Foo() => Console.WriteLine("A.Foo()");
}
public class B : A
{
public new void Foo() => Console.WriteLine("B.Foo()"); // Static binding (hiding)
}
public class C : A
{
public override void Foo() => Console.WriteLine("C.Foo()"); // Dynamic binding (overriding)
}
/*public class D : A // WARNING: new or override required
{
public void Foo() => Console.WriteLine("D.Foo()");
}*/
public class E : C
{
public sealed override void Foo() => Console.WriteLine("E.Foo()"); // C.Foo() is implicitly virtual
}
/*public class F : E // ERROR: sealed method cannot be overridden
{
public override void Foo() => Console.WriteLine("F.Foo()");
}*/
public class G : E
{
public new void Foo() => Console.WriteLine("G.Foo()"); // … but it can be hidden
}
class MethodOverridingDemo
{
static void Main(string[] args)
{
A thing = new A();
B thing2 = new B();
C thing3 = new C();
A thing4 = thing2;
A thing5 = thing3;
A thing6 = new E();
A thing7 = new G();
thing.Foo(); // A.Foo()
thing2.Foo(); // B.Foo()
thing3.Foo(); // C.Foo()
thing4.Foo(); // A.Foo()
thing5.Foo(); // C.Foo()
thing6.Foo(); // E.Foo()
thing7.Foo(); // E.Foo()
}
}
}

Tested in Visual Studio Community (C#6). This code does not work directly in Unity as Expression-bodied members were introduced in C#6 and Unity uses C#4 at this point. I have created an alternative Gist, adapted to Unity.