Both your samples of code give the same result because the addition of the new
modifier doesn't change the output of the compiler - it just gets rid of the compiler warning CS0108. Without the new
, the compiler is adding it for you:
This warning informs you that you should use new
; the variable is declared as if new had been used in the declaration.
That said, hiding with new
and overriding do not have the same effect as each other, due to polymorphism.
Consider the following case (try it online):
Main class:
public class Program
{
public static void Main()
{
Developer developer = new Developer();
PrintSalaryWithHiding(developer);
PrintSalaryWithOverriding(developer);
}
public static void PrintSalaryWithHiding(Employee employee)
{
Console.WriteLine("Salary (with hiding): " + employee.SalaryWithHiding);
}
public static void PrintSalaryWithOverriding(Employee employee)
{
Console.WriteLine("Salary (with overriding): " + employee.SalaryWithOverriding);
}
}
Base class (note that SalaryWithHiding
is not virtual but SalaryWithOverriding
is):
public abstract class Employee
{
public int SalaryWithHiding
{
get
{
return 10000;
}
}
public virtual int SalaryWithOverriding
{
get
{
return 10000;
}
}
}
Derived class (note the new
before SalaryWithHiding
and the override
before SalaryWithOverriding
):
public class Developer : Employee
{
public new int SalaryWithHiding
{
get
{
return 50000;
}
}
public override int SalaryWithOverriding
{
get
{
return 50000;
}
}
}
The result of this is
Salary (with hiding): 10000
Salary (with overriding): 50000
Why?
It's because the new
keyword tells the compiler that if you have a instance of a Developer
, declared as a Developer
, calling the SalaryWithHiding
method will call the one in the Developer
class instead of the one in the Employee
class (i.e. it hides it).
When you have a instance of a Developer
, declared as an Employee
, calling the SalaryWithHiding
method calls the one in the Employee
class.
You can see this in the following cut-down example (try it online):
Main class:
public class Program
{
public static void Main()
{
Developer developer = new Developer();
Console.WriteLine("Developer salary when declared as developer: " + developer.SalaryWithHiding);
// these are the same object!
Employee employee = developer;
Console.WriteLine("Developer salary when declared as employee: " + employee.SalaryWithHiding);
}
}
Employee:
public abstract class Employee
{
public int SalaryWithHiding
{
get
{
return 10000;
}
}
}
Developer:
public class Developer : Employee
{
public new int SalaryWithHiding
{
get
{
return 50000;
}
}
}
The result is:
Developer salary when declared as developer: 50000
Developer salary when declared as employee: 10000
Summary
In general, I would say you should only use the new
modifier if you know what you are doing, as it breaks polymorphism: as you saw in your own example, when you had
ClassA ab = new ClassB();
ab.printInfo();
it called the method in ClassA
as though you hadn't declared a separate method in ClassB
which have a different result. That can be very confusing. You would have been much better off making the method in the base virtual
and overriding it in the derived class instead, unless you wanted that behaviour for some reason. In my (contrived) example using new
to hide a method resulted in an incorrect salary!