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.
Related
Below code, A is base class and B is a derived class. When I do A a1 = new B(); and call what a1 can see, I see that it can only see class A field because a1 is of A type so it can not see B specific members and this is what I expected too. But when I call a1.Display() it prints out B's display method. How come a1 can not see B field but can reach B's display method?
using System;
namespace Test
{
class A
{
public int varOfClassA = 5;
public virtual void Display()
{
Console.WriteLine("I am Class A");
}
}
class B : A
{
public int varOfClassB = 10;
public override void Display()
{
Console.WriteLine("I am class B");
}
}
class Program
{
static void Main(string[] args)
{
A a1 = new B();
Console.WriteLine(a1.varOfClassA); //prints out "5"
a1.Display(); //prints out "I am class B" why???
}
}
}
That's because the method Display() is declared in B as overrides.
Every member that overrides a base class member will be executed whether the reference type is of the derived or of the base class.
When you do A a1 = new B(); what you have is an instance of B, not an instance of A.
However, since the reference is of type A, you can only access whatever methods of B that also exists in A, either inherited as is or overridden.
As a rule, in such cases, when your code executes a method on a1, the method that gets executed is the B method, since that's the type of instance you have. However, this rule does have an exception - and that is when instead of override, the method in B is declared as new. In such cases, the method (or property) of A is executed, even though your instance is of type B:
class A
{
public virtual void Display()
{
Console.WriteLine("I am Class A");
}
public int MyIntValue { get{ return 5; } }
}
class B : A
{
public override void Display()
{
Console.WriteLine("I am class B");
}
public new int MyIntValue { get{ return 5; } }
}
Using the above classes:
A a1 = new B();
a1.Display(); // Displays "I am class B"
Console.WriteLine(a1.MyIntValue.ToString()); // Displays "5"
You can see a live demo on rextester.
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.
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 have a Base class and 2 derived classes. I have a variable of base class which can hold one of the derived classes. I want to send that variable to a method which receives derived classes.
What can I do to resolve this problem without explicit cast since I don't know what the variable holds?
code:
Class A{
virtual public void foo1() {/.../}
}
Class B : A{
override public void foo1() {/.../}
}
Class C : A{
override public void foo1() {/.../}
}
Class D{
public foo(B argB) {/.../}
public foo(C argC) {/.../}
// in main
D varD = new D();
A varA = new B();
varD.foo(varA); //--->> Problem here need explicit casting
A varC = new C();
varD.foo(varC); //--->> Problem here need explicit casting
I don't know what derived class I'm sending to varD.foo and I want different handling of different derived classes. What can I do?
This is not what polymorphism is about - you can not pass a base class where a specialized class is expected, even when explicitly casting. Polymorphism works the other way: You can pass a specialized class wherever the base class is expected.
What you should do is make D.foo expect A and you will automatically be fine. If you add any methods to B or C which have no base implementation in A, you need to pass B anyway and can not cast an A to B or D.
Just make foo an abstract instance method of A and override the implementation in B and C. You could even keep your class D and delegate the actual work to there but it depends if this is a good idea.
Here the code with delegation to D. Also note that I omitted the method foo1() in all classes.
public abstract class A
{
public abstract void foo(D d);
}
public sealed class B : A
{
public override void foo(D d)
{
d.foo(this);
}
}
public sealed class C : A
{
public override void foo(D d)
{
d.foo(this);
}
}
public sealed class D
{
public void foo(B b) { [...] }
public void foo(C c) { [...] }
}
Now you can use virtual method dispatching to call the correct method.
D d = new D();
A b = new B();
A c = new C();
b.foo(d); // Calls B.foo(D) and in turn D.foo(B).
c.foo(d); // Calls C.foo(D) and in turn D.foo(C).
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.