C# - What is the difference between new and override + virtual

This is an area of C# where there is a big "gotcha". Using the new keyword or using the virtual + override keywords behave very differently, we will start with virtual.

Virtual and override

If we have the following class MyClass with a virtual Get() method:

public class MyClass
{
    public virtual string Get()
    {
        return "MyClass";
    }
}

We then create a class that inherits from MyClass and overrides the Get() method.

public class MyOverriddenClass : MyClass
{
    public override string Get()
    {
        return "MyOverriddenClass";
    }
}

If we instantiate MyOverriddenClass and call the method Get(), we get the string "MyOverriddenClass":

MyClass originalClass = new MyOverriddenClass(); //Declared as "MyClass" not "MyOverriddenClass"
Assert.AreEqual("MyOverriddenClass", originalClass.Get()); //passes

MyOverriddenClass overridenClass = new MyOverriddenClass();
Assert.AreEqual("MyOverriddenClass", overridenClass.Get()); //passes

The result is the same whether we declare it as MyClass or MyOverridenClass. Does this surprise you? It should not, the surprise is in the difference when we get to the new keyword - read on.

New Keyword

We will reuse the MyClass class from before (without virtual keyword) and make a MyNewClass class which uses the new keyword instead of override:

public class MyClass
{
    public string Get()
    {
        return "MyClass";
    }
}

public class MyNewClass : MyClass
{
    public new string Get()
    {
        return "MyClassUsingNew";
    }
}

If we do the same test as we did before:

MyClass originalClass = new MyNewClass(); //Declared as "MyClass" not "MyNewClass"
Assert.AreEqual("MyClassUsingNew", originalClass.Get()); //fails

MyNewClass overridenClass = new MyNewClass();
Assert.AreEqual("MyClassUsingNew", overridenClass.Get()); //passes

We see that the first assertion now fails. It calls the original method on MyClass rather than the new method on MyNewClass. This is because the new keyword creates a completely different method that only exists in that class. That is the big difference between using new or virtual/override keywords. Using virtual you can signal that this method is supposed to be overridden and then override it specifically with the override keyword. Using new you are creating a new method and hiding the original implementation (I like to think with brute force) and there is no relation between the two.

That is all

I hope you found this useful, please leave a comment down below if this was helpful - or even if not :)