I'm confused with the following scenario, we have a set of classes like this
public class A
{
public virtual string SomeMethod()
{
return "A";
}
}
public class B : A
{
public override string SomeMethod()
{
return "B";
}
}
public class C : B
{
public new virtual string SomeMethod()
{
return "C";
}
}
public class D : C
{
public override string SomeMethod()
{
return "D";
}
}
When i call the following method
private void Test()
{
A a = new D();
B b = new D();
C c = new D();
D d = new D();
Console.WriteLine(a.SomeMethod()); //The method in class B is being called
Console.WriteLine(b.SomeMethod()); //The method in class B is being called
Console.WriteLine(c.SomeMethod()); //The method in class D is being called
Console.WriteLine(d.SomeMethod()); //The method in class D is being called
}
I'm getting the output like this
B B D D
Why is it that the inherited method is being called, instead of the method in the declared type, and why isn't the method in class D being called every time?
When you call SomeMethod on an instance of A (i.e. A foo = new <A or derived>()), you expect to get the most derived version of SomeMethod available. That's the whole point of inheritance. Your code only needs to deal with instances of the base class, but if those instances happen to really be of a derived class, the special dervied implementations are invoked. This is the behavior you get when you override a method.
This explains common scenarios like
A b = new B();
b.SomeMethod(); // B's implementation invoked
With new, you are not overriding the method, you are declaring a brand new method with the same name. This method exists only on the class that declared it and its children, it's not part of the base classes and their inheritance chain.
So what does A a = new D(); a.SomeMethod(); do? The variable is declared as A, so any methods/properties/etc invoked against it have to be defined on A. C defined a new method SomeMethod (and D overrides it), but this method doesn't exist on A, so it cannot be invoked here. The most derived implementation of SomeMethod (as declared on type A) is in B, so this is the implementation which is invoked.
Same story for B b = new D(); b.SomeMethod();
It's only when we get to C c = new D(); c.SomeMethod() that the new method has a chance to execute. This is because the variable is a C, and thus the new method SomeMethod is for the first time declared on the variable type. And as stated above, the most derived possible version will be invoked, which in this case means the version overriden by D.
And I hope we are all on the same page for D d = new D(); d.SomeMethod() :)
Others have posted good links. Here's another thread that might help: C# and method hiding
And the last example here shows an even weirder scenario where the "new" method is declared as private, thus a further dervied type actually inherits the base version of the method, rather than inheriting the "new" version. http://msdn.microsoft.com/en-us/library/aa691135
I try to explain it in a different way.
virtual / override means, that you implement / change the behaviour of the same method. It is an implementation of polymorphism. With new, you create a completely new method. It happens to have the same signature as another method, but doesn't have anything to do with it.
When calling this methods, it depends on which type the reference has (compile time type), to choose the method you actually call.
Your code is equivalent to:
public class A
{
public virtual string SomeMethod()
{
return "A";
}
}
public class B : A
{
public override string SomeMethod()
{
return "B";
}
}
public class C : B
{
public virtual string AnotherMethod()
{
return "C";
}
}
public class D : C
{
public override string AnotherMethod()
{
return "D";
}
}
private void Test()
{
A a = new D();
B b = new D();
C c = new D();
D d = new D();
Console.WriteLine(a.SomeMethod()); //The method in class B is being called
Console.WriteLine(b.SomeMethod()); //The method in class B is being called
Console.WriteLine(c.AnotherMethod()); //The method in class D is being called
Console.WriteLine(d.AnotherMethod()); //The method in class D is being called
}
The compiler chooses to call AnotherMethod for reference of type C (and D).
That is a well-known behavior: when you hide method (with new) it is called only when you are accessing it through instance of hiding type; when you use instance of base class, original method is used.
Hiding is not overriding.
Related
This question already has answers here:
Why does this polymorphic C# code print what it does?
(5 answers)
Closed 6 years ago.
I have an example of code in C#
using System;
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
This code outline
B.F
B.F
D.F
D.F
I do not understand why in case a.F();
There is B.F ?
how MS said the virtual methods is represended by type of object in real time
I do not understand why in case a.F(); There is B.F ?
MSDN #
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
Bold content will explain to you why B.F is printed when A.F() is called.
The call to method F() from your inherited class object prints B.F for the object of type D downcasted to type A, because you override the method in class B (and class D).
Your test is an almost exact copy of the example provided in this MSDN post on virtual methods:
using System;
class A
{
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B: A
{
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test
{
static void Main() {
B b = new B();
A a = b;
a.F();
b.F();
a.G();
b.G();
}
}
In the example, A introduces a non-virtual method F and a virtual
method G. The class B introduces a new non-virtual method F, thus
hiding the inherited F, and also overrides the inherited method G. The
example produces the output:
A.F
B.F
B.G
B.G
Notice that the statement
a.G() invokes B.G, not A.G. This is because the run-time type of the
instance (which is B), not the compile-time type of the instance
(which is A), determines the actual method implementation to invoke.
Because methods are allowed to hide inherited methods, it is possible
for a class to contain several virtual methods with the same
signature. This does not present an ambiguity problem, since all but
the most derived method are hidden. In the example
In case of a.F() there is B.F because virtual void F in class A is override in B.
It is not override by C, because there is a new operator which does not override the virtual base method.
So if there is an instance of type D typed to A and you call F(), virtual method from the class A is called, but the latest override is taken into account. That is B.F.
In case of method overriding based on the type referent object hold method call will be decided.
In case of method hiding based on type of object method call will be decided.
Can any one explain me the method calling decision in overriding + hiding.
public class Base
{
public virtual void DoIt()
{
}
}
public class Derived : Base
{
public override void DoIt()
{
}
}
public class Derived1 : Derived
{
public new void DoIt()
{
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
Derived d = new Derived();
#1 b.DoIt(); // Calls Derived.DoIt
#2 d.DoIt(); // Calls Derived.DoIt
b = new Derived1();
d = new Derived1();
#3 b.DoIt(); // Calls Derived.DoIt
#4 d.DoIt();
}
}
#1 and #2 call Derived.DoIt because of run-time polymorphism.
#4 called Derived.DoIt because d is of type Dreived (Method hiding).
But why #3 called Derived.DoIt.
What is the calling sequence in case of overiding plus hiding in c#.
Thanks in advance
Because #3 is an instance of Base type. Here, the last derived method of Base resides in Derived class and hence it is being called.
new / method hiding / shadowing is different than method overriding in the sense that override means that you are customizing the base method whereas new means you are just providing a different implementation for the same method name.
In Method overriding it is decided on run-time which type's method to be called, but method hiding or shadowing is compile time thing, the compiler knows at compile time that which type's method is to called, when you use new keyword in derived type in method signature instead of override, that means that if you will call using reference of base class it will call base class implementation and if you use derived class reference it will call derived class method implementation.
The derived class implementation get's hidden from base class.
If you write it like this:
b = new Derived1();
b.DoIt() // (run-time) will call Dervied method implementation as Dervied has overridden
// so calling via base reference will call overridden implementation if any
//otherwise base class implementation will get called
Derived1 d1 = (Derived1)b;
d1.DoIt(); // (compile time) will call Derived1 method implementation due to hiding in Derived1
Derived d = (Derived)b;
d.DoIt(); // (run-time) will call Derived method implementation due to override
#3 calls Derived.DoIt() because the method was only hidden, it is still externally callable if using the appropriate cast. The variable b of is of type Base, and so you are accessing the methods available to Base. This is the one that is overwritten via Derived, so your result is the one from Derived.DoIt. Would you have a variable of type Derived1 and did a call to DoIt there, Derived1.DoIt would have been called instead.
public class Base
{
public virtual void DoIt()
{
Console.WriteLine("Base.DoIt was called!");
}
}
public class Derived : Base
{
public override void DoIt()
{
Console.WriteLine("Derived.DoIt was called!");
}
}
public class Derived1 : Derived
{
public new void DoIt()
{
Console.WriteLine("Derived1.DoIt was called!");
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
Derived d = new Derived();
Console.WriteLine("#1");
b.DoIt();
Console.WriteLine("#2");
d.DoIt();
b = new Derived1();
d = new Derived1();
Console.WriteLine("#3");
b.DoIt();
Console.WriteLine("#4");
d.DoIt();
Console.WriteLine("#5");
Derived1 e = new Derived1();
e.DoIt();
Console.ReadKey();
}
}
The runtime type of all the calling instances is D hence, all the invocations of F() should be the F() method declared in D.
using System;
class A
{
public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
public override void F() { Console.WriteLine("D.F"); }
}
class Test
{
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}
the output is:
B.F
B.F
D.F
D.F
Shouldn't the output be:
D.F
D.F
D.F
D.F
Versioning with the Override and New Keywords (C# Programming Guide)
If the method in the derived class is preceded with the new keyword,
the method is defined as being independent of the method in the base
class.
So you'r F methods from A and B are not connected with these from C and D, and that's why you get what you get.
At runtime CLR looks for virtual method implementation that should be used starting from type the variables is declared to be up to type it really is. For a.F() and b.F() it stops on B.F() declaration, because C.F() is a different method (because of new).
It should not...
A a = d;
This means you are creating a class of type A. And since you are explicitly overriding the related method in class B; A employs the method in the B class.
On the otherhand, in this line;
new public virtual void F() { Console.WriteLine("C.F"); }
You are declaring that you will not use the F() method from base by using the new keyword.
If you had overriden the F() method in D and C classes, all instance would have called the F() method declared in D class.
You are using new public virtual void F() in class C:B. It means that the F() in class C and the F() in class B are different method.
So when you override C to class D, the method F() in class D is overwritten from class C, not B.
Another obvious example can be like this:
C c = new C();
B b = c;
b.F();
c.F();
class A
{
public virtual void WhoAreYou() { Console.WriteLine("I am an A"); }
}
class B : A
{
public override void WhoAreYou() { Console.WriteLine("I am a B"); }
}
class C : B
{
public new virtual void WhoAreYou() { Console.WriteLine("I am a C"); }
}
class D : C
{
public override void WhoAreYou() { Console.WriteLine("I am a D"); }
}
C c = new D();
c.WhoAreYou();// "I am a D"
A a = new D();
a.WhoAreYou();// "I am a B" !!!!
How the reference is allocated internally,reference A contains the reference of B?
Can any one explain Whats going On?
In class C, the method WhoAreYou() doesn't override the base class method, as it is defined with new keyword which adds a new method with the same name which hides the base class method. That is why this:
C c = new D();
c.WhoAreYou();// "I am a D"
invokes the overridden method in D which overrides its base class method defined with new keyword.
However, when the target type is A, then this:
A a = new D();
a.WhoAreYou();// "I am a B" !!!!
invokes the overridden method in B, as you're calling the method on a of type A whose method is overriden by B.
Your class C WhoAreYou() method is 'new', and therefor hiding the one from B. That means that the override in class D is overriding C's method instead of B's (which is overriding A's).
Since you have a reference to an A, the furthest down the hierarchy of it's WhoAreYou() function is the one in class B.
http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
It is mean, that the C's
public new virtual void WhoAreYou(){}
breaks the chain of virtual methods.
When you call the method WhoAreYou() of D by reference of A. The virtuality starts work, but it breaks at C.
Could someone please explain what the difference is between these two examples?
Class A
protected virtual string GetData()
Class B
private override string GetData()
And the following:
Class A
protected string GetData()
Class B
private string GetData()
Assuming that 'Class B' inherits from 'Class A'.
I always assumed that you need to use virtual in the superclass and override in the subclass if you want overriding of a method, however I tried removing the keywords and the program compiled fine. What exactly is the difference, if any?
The second example that you showed hides the GetData of the parent, it doesn't override it.
Example:
private class Base
{
public virtual void Test()
{
Console.WriteLine("Base");
}
public void Test2()
{
Console.WriteLine("Base");
}
}
private class Derived : Base
{
public override void Test()
{
Console.WriteLine("Derived");
}
public void Test2()
{
Console.WriteLine("Derived");
}
}
static void Main()
{
Base b = new Base();
Derived d = new Derived();
Base dInB = new Derived();
b.Test();
d.Test();
dInB.Test();
b.Test2();
d.Test2();
dInB.Test2();
Console.ReadKey(true);
}
It outputs:
Base // Base.Test()
Derived // Derived.Test()
Derived // Derived.Test()
Base // Base.Test2()
Derived // Derived.Test2()
Base // You think you're calling Derived.Test2(), but you actually call Base.Test2()
Actually this sample is invalid, because it should use the new keyword in public new void Test2() in the Derived class.
It works just like operator overloading. It doesn't actually override anything. When you have the exact type Derived it calls the new method.
You have to be really careful with hiding members, it is nothing like overriding (classes) or implementing (interfaces) at all. Only when you have the exact type it'll call a new method, otherwise it'll still call the base type's method!
The difference is that in the first case you are overriding and in the second case you are hiding which is completely different.
In the first case:
class B: A
{
void Foo()
{
B b = new B();
A a = b;
a.GetData() //B's GetData() will be called
b.GetData() //B's GetData() will be called
}
}
On the other hand in the second case:
class B: A
{
void Foo()
{
B b = new B();
A a = b;
a.GetData() //A's GetData() will be called
b.GetData() //B's GetData() will be called
}
}
In the second case you are simply hiding A's implementation of GetData() but you will always be able to call A's implementation through a variable typed A even if the variable refers to a instance of type B. Note that this is completely different from how overriding behaves.
public class A
{
public virtual string GetData() { return "A";}
}
public class B : A
{
public override string GetData() { return "B"; }
}
What do you expect if you are using the classes as in the following codeblock?
A a = new A();
B b = new B();
A c = new B();
Console.WriteLine(a.GetData());
Console.WriteLine(b.GetData());
Console.WriteLine(c.GetData());
This will print "A" "B" "B". The variable c is stored as A type but when executing the method the code is resolved to the "real" implementation. (see google for virtual function table and resolving principle)
If you do not use virtual and override as in the code below this will print "A" "B" "A".
public class A
{
public string GetData() { return "A";}
}
public class B : A
{
public new string GetData() { return "B"; }
}