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.
Related
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();
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.
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"; }
}
I'm trying to override an overridden method (if that makes sense!) in C#.
I have a scenario similar to the below, but when I have a breakpoint in the SampleMethod() in the "C" class it's not being hit, whilst the same breakpoint in the "B" method is being hit.
public class A
{
protected virtual void SampleMethod() {}
}
public class B : A
{
protected override void SampleMethod()
{
base.SampleMethod();
}
}
public class C : B
{
protected override void SampleMethod()
{
base.SampleMethod();
}
}
Thanks in advance!
Edit:
Ok, the context would help:
This is in the context of a composite control so class A inherits from CompositeControl and calls SampleMethod() after overriding the CreateChildControls() method.
Overriding can be performed in a chain as long as you like. The code you have shown is correct.
The only possible explanation for the behaviour you are seeing is that the object to which you are referring is actually of type B. I suggest that you double check this, and if things still don't make sense, post the other appropiate code.
Without seeing the code that calls SampleMethod, my guess would be that you have an object of type B and call SampleMethod on that.
The breakpoint is more than likely not being hit because you actually instantiated an instance of the "B" class.
Method override resolution works based on the actual runtime type of the class whose method should be called. So, if you had the following code:
C c = new C();
c.SampleMethod();
and the following:
C c = new C();
B b = (B)c;
b.SampleMethod();
both the runtime types of the class whose SampleMethod will be called is type B.
That solution works fine; although to actually use it outside the class the method is in, you need to set the access of SampleMethod to public rather than protected in all of the cases it appears, so:
public class A
{
public virtual void SampleMethod()
{
Console.WriteLine("lol");
}
}
public class B : A
{
public override void SampleMethod()
{
base.SampleMethod();
}
}
public class C : B
{
public override void SampleMethod()
{
base.SampleMethod();
}
}
for Overriding more than once in the hierarchy use something like this
// abstract class
abstract class A
{
public abstract void MethodOne();
}
// class B inherits A
class B : A
{
public override void MethodOne()
{
Console.WriteLine("From Class B");
}
}
// class C inherits B
class C : B
{
public override void MethodOne()
{
Console.WriteLine("From Class C");
}
}
// class D inherits C
class D : C
{
public override void MethodOne()
{
Console.WriteLine("From Class D");
}
}
// etc......
// class Main method Class
class MainClass
{
public static void Main()
{
B[] TestArray = new B[3];
B b1 = new B();
C c1 = new C();
D d1 = new D();
TestArray[0] = b1;
TestArray[1] = c1;
TestArray[2] = d1;
for (int i = 0; i < TestArray.Length; i++)
{
TestArray[i].MethodOne();
}
Console.ReadLine();
}
}
I did it in this code in this link
http://www.4shared.com/rar/0SG0Rklxce/OverridingMoeThanOnce.html
Method overriding is OOP feature that allows a child class to provide a specific implementation of a method that is already provided by one of its parent classes.