If you come from a C++ or Java background to C# then you will of course notice some strange keywords introduced to this new language.
The first reaction will be, what are these things for and why were they added?
Especially that, until now people were able to develop programs using the existing languages without problems. Among the set of new keywords added to C# there are new and "override" modifiers. Although "new" may not seem that new to you, its usage however for a method modifier is completely new.
The "new" modifier
Similarly to C++ , C# allows redefinition of inherited methods in the derived classes at the cost of hiding the inherited ones.
Although hiding is not an error, it does cause the compiler to issue a warning. To suppress this warning you need to include the "new" modifier in the derived method.
The real benefit of this feature is to confirm you intentionally want to hide the base method and this did not happen by accident or misspelling.
Conversely, if you declare a method as new and it does not really hide a base method then the compiler will also issue a warning, that can be suppressed by removing the "new" modifier.
Consider the following example:
public class baseHello
{
public void sayHello()
{
System.Console.WriteLine("base says hello");
}
}
class derivedHello:BaseHello
{
public void sayHello()
{
System.Console.WriteLine("derived says hello");
}
}
The preceding code will compile fine but the compiler warns you that the method derivedHello.sayHello() hides the method baseHello.sayHello():
warning CS0114: 'derivedHello.sayHello()' hides inherited member 'baseHello.sayHello()'. To make the current method override that implementation, add the override keyword. Otherwise add the new keyword.
As the warning suggests, it is preferable to use "new" as in the following:
class derivedHello:BaseHello
{
new public void sayHello()
{
System.Console.WriteLine("derived says hello");
}
}
The "override" modifier
As you certainly know, every object oriented language implements polymorphism that essentially provides multiple implementations for the same interface.
Whereas all methods in Java are virtual by default, C++ and C# requires that methods be explicitly defined as being virtual using the "virtual" modifier in C++ and C# or the "abstract" modifier in C# only (abstract is equivalent to pure virtual in C++ : virtual type methodName(some params) = 0; ).
In order to provide a different version for the same method, it suffices to derive the base class and redefine the virtual method using the same name and signature, but with a different body, plus the "override" modifier. This may seem annoying at first, especially since C++ and Java developers did not need to do that. However experience with large projects has shown that many runtime problems occur when some modifications were needed in the virtual base method signature that necessarily require the same modification in all the derived classes that provide their own version.
Look at this Java example:
public class baseHello
{
public void sayHello()
{
System.out.println("baseHello says HELLO");
}
}
public class derivedHello extends baseHello
{
public void sayHello()
{
System.out.println("derivedHello says HELLO");
}
}
In the preceding example the class derivedHello inherits and redefines the method sayHello() from the baseHello class.
Now suppose that at some time in the project the designer determines that the sayHello() method should take a String parameter.
The change in the baseHello will be as follows:
Public class baseHello
{
public void sayHello(String name )
{
System.out.println("baseHello says HELLO to "+name);
}
}
Now the base class is modified and still the hard work to do is to modify all the derived classes and that could be dozens. Failing to modify one derived class will result in a behavior different from expected as the following code will show:
public class TestHello
{
public static void print(baseHello hello)
{
hello.sayHello("TestHello");
}
public static void main(String[] args)
{
baseHello baseH= new baseHello();
derivedHello derivedH= new derivedHello();
print(baseH);
print(derivedH);
}
}
Running the TestHello class will result in the following two identical strings:
baseHello says HELLO to TestHello
baseHello says HELLO to TestHello
The reason is because you failed to change the derivedHello class to be conformed to the baseHello class so the latter is used when hello.sayHell("TestHello") is called.
Because the Java compiler does not have any idea that the sayHello() in a derived class is intended to override the sayHello(String name) in the base class, it does not complain about it and considers it as a new method defined only in the derived class.
After exposing the problem, here is what C# offers to solve the problem.
Every method that must override a virtual base method must be declared with the "override" modifier. The same example applied to C# becomes:
public class BaseHello
{
virtual public void sayHello(string name)
{
System.Console.WriteLine("BaseHello says hello to {0}",name);
}
class DerivedHello:BaseHello
{
override public void sayHello()
{// different signature
System.Console.WriteLine("DerivedHello says hello");
}
}
The compilation of the example will result the following error:
error CS0115:'DerivedHello.sayHello()': no suitable method found to override
Telling the method sayHello() in DerivedHello that it is intended to override sayHello(String name) in BaseHello has a different signature than its base method.
In that way, no matter how many times a class is derived, it is always possible to detect a difference in the method's name and signature at compile time.
Conclusion
As a conclusion, you have noticed that the "new" and "override" modifiers have a key role in preventing runtime flaws and sparing hours of debugging.