1

I read some material about the "new" keyword for method overhiding in C#. However I still don't see the significant purpose of that "new" keyword except to fix the warning "CS0108 C# hides inherited member. Use the new keyword if hiding was intended." in Visual Studio. For sample:

class ClassA
{
    public void printInfo()
    {
        Console.WriteLine("I'm A");
    }
}

Test Case 1:

class ClassB : ClassA
{
    public void printInfo()
    {
        Console.WriteLine("I'm B");
    }
}
class Program
{
    static void Main(string[] args)
    {
        ClassA a = new ClassA();
        a.printInfo();
        ClassB b = new ClassB();
        b.printInfo();
        ClassA ab = new ClassB();
        ab.printInfo();
        Console.ReadKey();
     }
}

And Test Case 2 with "new" keyword:

class ClassB : ClassA
{
    public new void printInfo()
    {
        Console.WriteLine("I'm B");
    }
}
class Program
{
    static void Main(string[] args)
    {
        ClassA a = new ClassA();
        a.printInfo();
        ClassB b = new ClassB();
        b.printInfo();
        ClassA ab = new ClassB();
        ab.printInfo();
        Console.ReadKey();
     }
}

They both have the same output:

I'm A
I'm B
I'm A

The difference is that "new" keyword fixes the warning.

Could someone show me more samples for the helpfulness of the "new" keyword here ?

Hiosdroid
  • 31
  • 1
  • 6
  • Are you asking why you'd want to write code that compiles without warnings and makes your intentions clear? – UnholySheep May 07 '17 at 11:22
  • How can test case 1 and 2 have the same output? More specifically, how does your first test case even compile? –  May 07 '17 at 11:23
  • @FurkanKolcu this question has nothing to do with `virtual` methods, it's about method hiding – UnholySheep May 07 '17 at 11:25
  • Also, see here for a specific scenario where the `new` modifier is helpful: http://stackoverflow.com/questions/5709034/does-c-sharp-support-return-type-covariance/5709191#5709191. But always keep in mind that hiding methods can have unwanted side effects if one does not meticulously pays attention, hence the compiler warning. –  May 07 '17 at 11:28
  • @elgonzo I'm using VS Community 2015 and no error compilation for both test cases. – Hiosdroid May 07 '17 at 11:30
  • @Hiosdroid, you are right, it compiles. I momentarily thought case 1 would cause a compiler error, but it causes a compiler warning only. Sorry, my bad... :) –  May 07 '17 at 11:32
  • 3
    Note that there's no such term as "overhiding" - there's *overriding* and there's *hiding* but they're completely different. – Jon Skeet May 07 '17 at 11:49

3 Answers3

0

MSDN has a good article about when to use Override and New keywords took a look at it Knowing When to Use Override and New Keywords

The main idea is that when you are writing public new void function() you are telling the compiler that you know that this method is being hidden by the method from baseclass and the warning is disappearing. Now you will be able to use this method from instance of the derived class and the base method from instance of the base class or boxed to the base class.

Samvel Petrosov
  • 7,580
  • 2
  • 22
  • 46
  • @Hiosdroid, in a comment to your question i have given you a link that explains a scenario where hiding methods might be useful. What you don't seem to understand is that hiding methods can also be dangerous. Hence the compiler tries its best to make you aware of the fact that you are hiding a method. See also here about why the compiler asks you about using the `new` modifier: http://stackoverflow.com/a/19671643/2819245 (sorry, shameless self-plug) –  May 07 '17 at 11:53
0

There is no difference between both codes. The compiler is simply warning you that you might be unaware of the fact that you are hiding A.printInfo and it's simply drawing your attention to it.

In large codebases where maybe you don't even own A it's easy to write a method in a derived class that has the same signature as an existing method in the base class.

With the keyword new you get three immediate advantages:

  1. You are informing the compiler that you are aware of the fact and you are intentionally hiding a method/property.
  2. You are making it clear to anyone reviewing or mantaining your code in the future that you are hiding a method/property.
  3. Your code actually compiles if warnings are set to be treated as compile time errors, something that is advisable and commonly the case in any decent quality coding environment.
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Thank u, I think this answer makes me satisfied about my test cases. I upvoted ur answer but I have no reputation enough to do it. :) – Hiosdroid May 07 '17 at 12:47
0

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!

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92