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 ?
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:
You are informing the compiler that you are aware of the fact and you are intentionally hiding a method/property.
You are making it clear to anyone reviewing or mantaining your code in the future that you are hiding a method/property.
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.
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.
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!
Related
disclaimer: i am totally newbie to this world of coding!
in my course on learning c#, i read this article.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords.
code:
public class Car
{
public void DescribeCar()
{
Console.WriteLine("Car: Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
Console.WriteLine("Car: Standard transportation.");
}
}
public class ConvertibleCar : Car
{
public new void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
}
ConvertibleCar myCC = new ConvertibleCar();
myCC.DescribeCar();
myCC.ShowDetails();
//Output
Car: Four wheels and an engine.
Car: Standard transportation.
ConvertibleCar: A roof that opens
Question: i expect with my understanding i should get "ConvertibleCar: A roof than opens" in my second and third line of output.
what is it different when calling ShowDetails directly on the derived class, and from within a method in the base class.
PS: the showdetials is set at new in the derived class.
To get your expected output, use override in place of new:
public override void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
If you use new, you shadowed the ShowDetails method in the base class. This means that the derived class implementation will only be used when you call the method from a derived class variable.
override does something different. If ShowDetails is overridden, then the derived class implementation will always be used as long as the object's underlying type is the derived class, no matter the type of the variable.
This explains why the second line of output is different. The second line is produced from this line:
public void DescribeCar()
{
Console.WriteLine("Car: Four wheels and an engine.");
ShowDetails(); <--------
}
ShowDetails means this.ShowDetails. this is of type Car but actually refers to an object of ConvertibleCar. Since ShowDetails is shadowed, it calls the implementation of Car (because this is of type Car!)
The new keyword used for the hiding base member/method. So
public new void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
ShowDetails method is a new method for ConvertibleCar class and the base class ShowDetails method is completely different and it is not in the inheretance chain. Imagine that, you could define the method name like ShowDetails2 in the ConvertibleCar class. It would be same case.
Also, if you use the override keyword instead of new, the ConvertibleCar class would override the ShowDetails method.
public class ConvertibleCar : Car
{
public override void ShowDetails()
{
Console.WriteLine("ConvertibleCar: A roof that opens up.");
}
}
And output would be;
Car: Four wheels and an engine.
ConvertibleCar: A roof that opens.
ConvertibleCar: A roof that opens.
Because with new you effectively shadowed ShowDetails (in fact, in VB.NET there's a Shadows keyword for this). Moreover, with new you can make ShadowDetails a property!
Let's create two classes: Base and Derived:
class Base
{
public virtual int GetInt()
{
return 10;
}
}
class Derived : Base
{
public new int GetInt()
{
return 11;
}
}
Now, let's test them:
Base b;
Derived d;
int x;
b = new Derived();
d = new Derived();
x = b.GetInt(); // x = 10 [Base.GetInt()]
x = d.GetInt(); // x = 11 [Derived.GetInt()]
As you see, although b is assigned Derived, it still refers to Base.
But let's do something completely different - let's turn method into a property!
class Derived : Base
{
public new int GetInt
{
get { return 11; }
}
}
Now when we run previous test code we will see that x = 10:
x = d.GetInt(); // x = 10
But, wait, we don't have GetInt() method in Derived class! Why the code is compiled? It's simple - because we shadowed GetInt() method with GetInt property, now GetInt() is called from Base! To confuse things more, the IntelliSense doesn't show GetInt() method on d variable, but the compiler is satisfied. To get 11, you need to call property:
x = d.GetInt;
You can also turn GetInt() method into delegate:
class Derived : Base
{
public new delegate int GetInt();
}
and use it:
Derived.GetInt getIntDelegate = () => 12;
Console.WriteLine(getIntDelegate()); // Prints 12
I have read an article regarding the new keyword. It says it is used to hide methods. This is example they give:
using System;
namespace ConsoleApplication3
{
class SampleA
{
public void Show()
{
Console.WriteLine("Sample A Test Method");
}
}
class SampleB:SampleA
{
public void Show()
{
Console.WriteLine("Sample B Test Method");
}
}
class Program
{
static void Main(string[] args)
{
SampleA a = new SampleA();
SampleB b = new SampleB();
a.Show();
b.Show();
a = new SampleB();
a.Show();
Console.ReadLine();
}
}
}
Output:
Sample A Test Method
Sample B Test Method
Sample A Test Method
So my question isn't the new keyword used to instantiated an object? and its used to allocate memory for new created objects? Then how can method hiding be done using it? And is above example correct?
new is used for 3 different things. You could say there are 3 different keywords with the same name.
It's an operator, used to invoke constructors. Example: new object();
It's a modifier, used to hide an inherited member from a base class member. Example:
class Base {
public void MyMethod() {
//Do stuff
}
}
class Derived : Base {
public new void MyMethod() {
//Do other stuff
}
}
It's a generic type constraint, used to indicate that a generic type parameter has a parameterless constructor. Example:
class MyGenericClass<T> : where T : new() { ... }
Source: new
Isn't the new keyword used to instantiated an object?
Yes it is. Among other things.
then how can method hiding done using it?
The new keyword in the context of method and property definitions has another meaning than the new keyword used to instantiate objects. The new keyword in that context tells that there is a new start of the inheritance tree of that particular method or property. That's all.
Then how can method hiding be done using it? And is above example
correct?
Programming language syntax, grammar and semantics are just an arbitrary set of conventions and specifications. That is, C# can invent one, two or dozen of usages of a given keyword like new.
When new is used during a class member declaration, it means that you're re-using an identifier:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
As you can check in above code sample, B also implements a Text property, but since derives from A which has also defined a Text property, there's a naming collision.
The so-called new keyword can be used to re-use Text identifier and being able to implement another property Text which may behave absolutely different than the one implemented in the base class. See that Text on B is of type int!
The most important point here is that re-using identifiers isn't the same as using polymorphism, where a class method or property override must match base class' member signature:
public class A
{
public virtual string Text { get; set; }
}
public class B : A
{
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
}
Also, re-used identifiers are dangerous:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
B b = new B();
b.Text = 4;
// Upcast B to A
A a = b;
a.Text = "Bye bye";
Console.WriteLine(a.Text); // Output: Bye bye
Console.WriteLine(b.Text); // Output: 4
See the output of Text. Since re-using identifiers isn't polymorphism, and in above case both are completely different properties, there's an A.Text and B.Text that can be set separately.
To hide an inherited member, declare it in the derived class by using the same member name, and modify it with the new keyword. For example:
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'.
new public static int x = 100;
static void Main()
{
// Display the new value of x:
Console.WriteLine(x);
// Display the hidden value of x:
Console.WriteLine(BaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
/*
Output:
100
55
22
*/
You can read more in here
There are two clarifications I need which I am trying to understand.
I see that, I can access the variable "i" using "base" keyword as well as using the object. Is there any difference of it? I think, creation of object is memory consuming and hence we use base keyword itself to call base class members in derived class?
When to use this.i and base .i and object.i?
class Program
{
public Program()
{
i = 20;
}
public readonly int i = 10;
}
class C : Program
{
public C() : base()
{
//base.i = 20;
}
public int i = 20;
public void Display()
{
C c = new C();
Console.WriteLine(base.i);//prints 20
Console.WriteLine(c.i);//prints 20
Console.WriteLine(this.i); //Also prints 20 :D
}
static void Main()
{
C c = new C();
c.Display();
Console.ReadLine();
}
I tried to accept one answer as that helped me understand few things. But still, my question "the difference ans usage of 3 different styles at my context and in other contexts" is not clear. So please care to share your thoughts on this, I would appreciate it. I am sure there are millions like me who try to understand this :)
As for 1) You can use both to access the property as the sub class has extended it. There will only be a difference if you override that in the sub class or if you decide to create a field with the same name in your sub class.
EDIT:
To override it, you can make it a virtual property in the base class
public class Base
{
public virtual int i {get; set;}
}
public class Sub : Base
{
public override int i { get; set; }
}
Problem 2 : Your StackOverflow
you care creating a new instance of Program every time you create a new instance of Program it seems to be an infinite loop.
class Program
{
Program p = new Program(); // <-- this line here
In your case there is no difference. Difference comes when you have field with same name in base class and derived class(typically we don't have it).
class Program
{
public int i = 10;
}
class C : Program
{
public int i = 20;
public void Display()
{
C c = new C();
Console.WriteLine(base.i);//prints 10
Console.WriteLine(c.i);//prints 20
}
}
base keyword refers to base class, so base.i refers to "member named i" in base class.
Also worth noting that when you access a member with base keyword and it doesn't exist compiler will produce an error.
class Program
{
//public int i = 10; //No field named i
}
class C : Program
{
public int i = 20;
public void Display()
{
C c = new C();
Console.WriteLine(base.i);//Compile time error here
Console.WriteLine(c.i);//this refers to C.i field
}
}
Answer for Question 1
Base you can use when you want to refer you prent class from the child class.
Example :
public class A
{
public int i {get;set;}
}
public class B:A
{
publi void readvalueofi()
{ Console.Writeln(base.i); }
}
This also useful when you override method of parent and want to call parent method from child
Example :
public class Parent
{
public virtual void Print()
{
Console.WriteLine("Print in Parent");
}
}
public class Child : Parent
{
public override void Print()
{
base.Print();
Console.WriteLine("Print in Child");
}
}
Answer for Question 2 :
Reason for StackOverflow Exception
You're creating an private instance of Program when Program is created so this is sort of an endless loop:
your first create Program instance. When this instance is creating it creates a new instance of Program. This instance also creates an instance of Programand again, and again etc.
So basially it creates infinite loop over here.
Today, I found something in legacy code. It has "static new" for one function. It looks like this.
class Foo
{
public static void Do()
{
Console.WriteLine("Foo.Do");
}
}
class Bar: Foo
{
public static new void Do()
{
Console.WriteLine("Bar.Do");
}
}
I don't understand the static new modifier for the Do method in class Bar. In C#, static method can only be invoked with class name instead of object name. So, I don't think there is any difference between having the "new" and not.
Generally, if some syntax is unnecessary, C# just treat it is error.
Anybody has any idea about why C# allows such syntax?
If you remove the new from your code you get:
warning CS0108: 'Bar.Do()' hides inherited member 'Foo.Do()'. Use the new keyword if hiding was intended.
The C# compiler just warns you that you might be doing something you did not intend and asks you to insert the new keyword to confirm that you know what you are doing. Besides suppressing the warning, it has no other effects.
That applies only for external callers. Remember that you can call a static method of the base class, so something like this is valid:
class Foo
{
public static void Do() { Console.WriteLine("Foo.Do"); }
}
class Bar : Foo // :Foo added
{
public static void Something()
{
Do();
}
}
This is why the warning tells you to put the new, you want to avoid any confusion when doing this:
class Foo
{
public static void Do() { Console.WriteLine("Foo.Do"); }
}
class Bar : Foo // :Foo added
{
public static void Something()
{
Do();
}
public static new void Do() { Console.WriteLine("Bar.Do"); }
}
have a look at this
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'.
new public static int x = 100;
static void Main()
{
// Display the new value of x:
Console.WriteLine(x);
// Display the hidden value of x:
Console.WriteLine(BaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
/*
Output:
100
55
22
*/
Your example, to make it clear, should be
public class Foo
{
public static void Do() {}
}
public class Bar :Foo
{
public new static void Do() {}
}
In your example, the second class Bar doesn't seem to inherit from Foo. This seems to be a typo because it doesn't makes sense otherwise.
Assuming it to be a typo, the "new" modifier explicitly hides the base class version of the function Do(). This means that the derived version of the Do() method effectively replaces the base class version.
Using "new" here documents the fact that the inherited method is intended as a replacement for the base class version of Do().
For more information, see new Modifier (C#)
Coming from a C++ background, I've run into a snag with overloading based on a specific instance of a generic type. The following doesn't work since only once instance of the code for the Foo<T> class is ever generated, so inside the Method, the type of this is simply Foo<T>, not Foo<A> or Foo<B> as I'd hoped. In C++ I'm used to templates being instantiated as unique types.
using System.Collections.Generic;
class A
{
// Concrete class
}
class B
{
// Concrete class
}
class Bar
{
public void OverloadedMethod(Foo<A> a) {} // do some A related stuff
public void OverloadedMethod(Foo<B> b) {} // do some B related stuff
public void OverloadedMethod(OtherFoo of) {} // do some other stuff
public void VisitFoo(FooBase fb) { fb.Method(this); }
}
abstract class FooBase
{
public abstract void Method(Bar b);
}
class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
class OtherFoo : FooBase
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Program
{
static void Main(string[] args)
{
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo<A>());
ListOfFoos.Add(new Foo<B>());
Bar b = new Bar();
foreach (FooBase fb in ListOfFoos)
b.VisitFoo(fb);
// Hopefully call each of the Bar::Overloaded methods
}
}
Is there a way to get something like this to work in C#? I'd rather not have to duplicate the code in Foo as separate classes for every type I want to use it for.
Edit:
Hopefully this is a little clearer.
I now have a genuinely complete piece of code which demonstrates the problem. Note to OP: please try compiling your code before posting it. There were a bunch of things I had to do to get this far. It's good to make it as easy as possible for other people to help you. I've also removed a bunch of extraneous bits. OtherFoo isn't really relevant here, nor is FooBase.
class A {}
class B {}
class Bar
{
public static void OverloadedMethod(Foo<A> a) { }
public static void OverloadedMethod(Foo<B> b) { }
}
class Foo<T>
{
// Class that deals with As and Bs in an identical fashion.
public void Method()
{
// Doesn't compile here
Bar.OverloadedMethod(this);
}
}
Yes, this doesn't compile. What did you expect it to do, exactly? Bear in mind that the overload resolution is performed at compile time, not execution time. As fallen888 says, you could cast and call the appropriate overloaded method - but which of the two overloads would you expect the compiler to pick otherwise? What do you want it to do with Foo<string> instead of Foo<A> or Foo<B>?
This all goes to demonstrate that .NET generics are indeed significantly different from C++ templates, of course...
I haven't tried it but it seems you should be able to achieve what you want by making A & B visitable (e.g. with the acyclic visitor pattern).
This works for the static case. Dealing with instance functions would be a bit more complicated. This post from Jon Skeet might provide a reasonable way to deal with instance methods.
class Program
{
static void Main(string[] args)
{
var testA = new Foo<A>();
testA.Method();
var testB = new Foo<B>();
testB.Method();
Console.ReadLine();
var testString = new Foo<string>(); //Fails
testString.Method();
Console.ReadLine();
}
}
class A { }
class B { }
class Bar
{
public static void OverloadedMethod(Foo<A> a)
{
Console.WriteLine("A");
}
public static void OverloadedMethod(Foo<B> b)
{
Console.WriteLine("B");
}
}
class Foo<T>
{
static Foo()
{
overloaded = (Action<Foo<T>>)Delegate.CreateDelegate(typeof(Action<Foo<T>>), typeof(Bar).GetMethod("OverloadedMethod", new Type[] { typeof(Foo<T>) }));
}
public void Method()
{
overloaded(this);
}
private static readonly Action<Foo<T>> overloaded;
}
Edit: I'm not sure that you can complete this as you're attempting. I've tried all sorts of tricks to attempt to get this to work and can't get it to compile. The best I can do is to pull the method call outside of my Generic class. If your method call is outside, then you can specifically define what T is in the generic. However, inside the method, at compile time, the compiler doesn't know what T will be so it doesn't know which overloaded method to call. The only way I can see around this is to use a switch to determine the type of T and manually specify the overload to call.
The best I can do is this, which isn't quite what you're after, but it could be used to a similar effect:
class Stuff<T>
{
public T value { get; set; }
}
class Program
{
static void DummyFunc(Stuff<int> inst)
{
Console.WriteLine("Stuff<int>: {0}", inst.value.ToString());
}
static void DummyFunc(Stuff<string> inst)
{
Console.WriteLine("Stuff<string>: {0}", inst.value);
}
static void DummyFunc(int value)
{
Console.WriteLine("int: {0}", value.ToString());
}
static void DummyFunc(string value)
{
Console.WriteLine("string: {0}", value);
}
static void Main(string[] args)
{
var a = new Stuff<string>();
a.value = "HelloWorld";
var b = new Stuff<int>();
b.value = 1;
var c = "HelloWorld";
var d = 1;
DummyFunc(a);
DummyFunc(b);
DummyFunc(c);
DummyFunc(d);
}
}
and got output:
Stuff<string>: HelloWorld
Stuff<int>: 1
string: HelloWorld
int: 1
I've got four overloaded functions referencing two referencing generic classes (one for int and one for string) and two referencing regular types (one for int and one for string) and it all works okay... is this what you're after?
Edit: The problem doesn't seem to be with the calling of the overloaded methods, it has to do with your foreach which is trying to convert all items in the list to the same type as the first in order to reference the overloaded method. The first item that doesn't conform to that exact definition will cause your compile to fail.
I was hoping to find an easier way to do this but for now I'm going with this:
Replace Foo<T> class with these classes:
abstract class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
}
class Foo_A : Foo<A>
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Foo_B : Foo<B>
{
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
And change the instantiations to
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo_A());
ListOfFoos.Add(new Foo_B());
This at least doesn't require dublicating the code in Foo<T>, and just requires me to forward the constructors.