I have simple three classes:
class A
{
public virtual void Write()
{
Console.Write("A");
}
}
class B:A
{
public override void Write()
{
Console.Write("B");
}
}
class C : B
{
public new void Write()
{
Console.Write("C");
}
}
And I am creating objects and calling their methods:
A a = new A();
a.Write();
A b = new C();
b.Write();
C c = new C();
c.Write();
And output will be: ABC
What I cannot understand is why these code produces B?:
A b = new C();
b.Write();
I thought that it should be C. However, I tested many times, and it is always B.
I understand that A b = new C() creates new object type of C. So output should be C. Or it is special behavior to call overridden method when we use it without casting?
Why does it happen? As we have not used any reference to B class.
It would work if you'd use ((C)b).Write();
With the new keyword you're not overriding the Write method for C but rather creating a new method only defined for C. So for your C you actually have 2 methods with a method name Write.
A c = new C();
c.Write(); //Output "B", you're calling the overridden method
((C)c).Write(); //Output "C", you're calling the method defined on C
//or
(c as C).Write();
The same happens when you would define c as C:
C c = new C();
c.Write(); //Output "C"
((A)c).Write(); //Output "B"
In the first example you're calling the new method defined on C. In the second line you are calling the Write method from A, which is overridden by B, hence the output "B".
Edit: (some more explanation)
Variable c is of type A, so that's what your compiler knows "c is an instance of A", it is not known that it is actually of a more derived type. When you call the method Write on it, it will invoke the method defined on A (which is overriden by B). Your base class A has no knowledge of your new method defined on C (that's what new does, create a new method), so unless you cast it to C to let the compiler know about the actual, derived type of c, the method of your base class will be called.
I now its really late and does not answer the question, but i needed that behavior and just in case some else need it i'll share it.
To get that beheavior you need to use interfaces, for example
interface Writer{
void write;
}
class A : Writer
{
void Writer.Write()
{
Console.Write("A");
}
}
And the same for the others. As you can see, you have to implement it explicity as well as call it explicity.
A c = new C();
((Writer) c).write()
;
Related
I have simple three classes:
class A
{
public virtual void Write()
{
Console.Write("A");
}
}
class B:A
{
public override void Write()
{
Console.Write("B");
}
}
class C : B
{
public new void Write()
{
Console.Write("C");
}
}
And I am creating objects and calling their methods:
A a = new A();
a.Write();
A b = new C();
b.Write();
C c = new C();
c.Write();
And output will be: ABC
What I cannot understand is why these code produces B?:
A b = new C();
b.Write();
I thought that it should be C. However, I tested many times, and it is always B.
I understand that A b = new C() creates new object type of C. So output should be C. Or it is special behavior to call overridden method when we use it without casting?
Why does it happen? As we have not used any reference to B class.
It would work if you'd use ((C)b).Write();
With the new keyword you're not overriding the Write method for C but rather creating a new method only defined for C. So for your C you actually have 2 methods with a method name Write.
A c = new C();
c.Write(); //Output "B", you're calling the overridden method
((C)c).Write(); //Output "C", you're calling the method defined on C
//or
(c as C).Write();
The same happens when you would define c as C:
C c = new C();
c.Write(); //Output "C"
((A)c).Write(); //Output "B"
In the first example you're calling the new method defined on C. In the second line you are calling the Write method from A, which is overridden by B, hence the output "B".
Edit: (some more explanation)
Variable c is of type A, so that's what your compiler knows "c is an instance of A", it is not known that it is actually of a more derived type. When you call the method Write on it, it will invoke the method defined on A (which is overriden by B). Your base class A has no knowledge of your new method defined on C (that's what new does, create a new method), so unless you cast it to C to let the compiler know about the actual, derived type of c, the method of your base class will be called.
I now its really late and does not answer the question, but i needed that behavior and just in case some else need it i'll share it.
To get that beheavior you need to use interfaces, for example
interface Writer{
void write;
}
class A : Writer
{
void Writer.Write()
{
Console.Write("A");
}
}
And the same for the others. As you can see, you have to implement it explicity as well as call it explicity.
A c = new C();
((Writer) c).write()
;
i have piece of code
public class A
{
public A()
{
Console.WriteLine("A");
}
B b = new B("From A");
}
public class B : A
{
public B()
{
Console.WriteLine("B");
}
public B(string str) //Getting exception here
{
Console.WriteLine("In B " + str);
}
}
public class C : A
{
B b = new B("From C");
public C()
{
Console.WriteLine("C");
}
}
class Program
{
static void Main(string[] args)
{
new C();
Console.ReadKey();
}
}
Here, i know that all properties are initialized first before base constructor called, but i am unable to find why i am getting Stackoverflow exception. Any Help ?? Thanks
Because B inherits from A, it inherits the
B b = new B("From A");
field. So whenever you create a B object it creates another B object, in an infinite recursive chain.
So in the actual Program you have, you create a C object. This then constructs a B object using the overload that takes a string ("From C"). You then get an exception on that constructor, because it then recursively creates infinite B objects.
Recursive infinite loop:
Every time you create a B, you create a new A (through inheritance).
Every time you create an A, you create a new B (through variable b).
Since B inherits from A
//public class B : A
And when you create object of B in class A,It goes in recursive infinite loop.
The problem above is due to cyclic instantiation.
Here our thinking of instantiation causes these kind of issues:
Here when we instantiate C we just do not get object of class C but, it in fact is the combination of C+B+A.
These kind of problems can be easily identified by drawing an object diagram with Arrows from instantiating object to instanted object.
My fret is: In the code presented below, it should display A then B. But it displays B then B. Why is it so?
What I feel is, constructor of A gets executed first when creating object of B. In that case, the method in B would not be hitted right? So it should be A.Display() and should result A. Also, then a.Display() should return B because we have override.
So I expect A then B. Because its not overloading but overriding. I know the definition of these things, I expect to understand the reason for this behavior and how it works internally as I am not convinced with BB but AB.
Code
class A
{
public A()
{
this.Display();
}
public virtual void Display()
{
Console.WriteLine("A");
}
}
class B :A
{
public override void Display()
{
Console.WriteLine("B");
}
}
class C
{
static void Main()
{
A a = new B();
a.Display();
Console.WriteLine();
Console.ReadLine();
}
}
Outputs
1) On override of Display method in the derived class yields the following:
A a = new A(); // ---> AA
B a = new B(); // ---> BB // I expect AB.
A a = new B(); // ---> BB // I expect AB.
2) using the NEW keyword in the Display method in derived class yields the following:
B a = new B(); // ---> AB // I Expect AA here.
A a = new B(); // ---> AA
A a = new A(); // ---> AA
3) More interesting findings are:
When I use base.Display() in the derived constructor with override of the base method in derived class, it gives me BAB
I do not see any logic at least in this. because, it should give BBB
What I feel is, constructor of A gets executed first when creating object of B.
Correct.
In that case, the method in B would not be hit right?
This is incorrect.
In similar code in C++ you would be correct. In C++ there is a rule that virtual function dispatch tables are built as the object is being constructed. That is, when the "A" constructor is entered, the vtable is filled in with the methods in "A". When control goes to the "B" ctor, the vtable is then filled in with the methods of B.
This is not the case in C#. In C# the vtable is filled in the moment the object comes out of the memory allocator, before either ctor is executed, and it does not change after that. The vtable slot for the method always contains the most derived method.
Therefore calling a virtual method in a ctor as you are doing here is a very bad idea. A virtual method can be called where the implementation is on a class whose ctor has not run yet! It might therefore depend on state that has not yet been initialized.
Note that field initializers run before all ctor bodies, so fortunately an override on a more derived class will always run after the field initializers of the overriding class.
The moral of the story is: simply don't do that. Don't ever call a virtual method in a ctor. In C++ you might get a different method than you expect, and in C# you might get a method that uses state that is not initialized. Avoid, avoid, avoid.
Why we shouldn't call virtual methods inside ctor? Is it because we get only the (latest derived) results only) always in the vtable?
Yes. Let me illustrate with an example:
class Bravo
{
public virtual void M()
{
Console.WriteLine("Bravo!");
}
public Bravo()
{
M(); // Dangerous!
}
}
class Delta : Bravo:
{
DateTime creation;
public override void M()
{
Console.WriteLine(creation);
}
public Delta()
{
creation = DateTime.Now;
}
}
OK, so the expected behavior of this program is that when M is called on any Delta, it will print out the time that the instance was created. But the order of events on new Delta() is:
Bravo ctor runs
Bravo ctor calls this.M
M is virtual and this is of runtime type Delta so Delta.M runs
Delta.M prints out the uninitialized field, which is set to the default time, not the current time.
M returns
Bravo ctor returns
Delta ctor sets the field
Now do you see what I mean when I say that the overriding method might rely on state that is not initialized yet? In any other usage of M, this would be fine because the Delta ctor would already be finished. But here M is called before the Delta ctor even starts!
You create an instance of an object B. It uses the code of the constructor that is defined on class A as you did not override it in B. But the instance is still B, so other methods called in the constructor are the ones defined in B, not A. Hence you see the result of Display() defined in class B.
Update based on update of the question
I'll try to explain the "weird" results you're getting.
When overriding:
B a = new B(); // ---> BB // I expect AB.
A a = new B(); // ---> BB // I expect AB.
This is covered above. When you override a method on a child class, this method is used if you're using an instance of the child class. This is a basic rule that the methods used are decided by the class of the instance of a variable, not by the class used to declare the variable.
When using new modifier for the method (hiding inherited method)
B a = new B(); // ---> AB // I Expect AA here.
Now there's two different behaviours here:
When the constructor is used, it's using the constructor in class A. As the inherited method is hidden in the child class, the constructor is using Display() method from class A and hence you see A printed.
When you later call Display() directly, the instance of the variable is B. For that reason, it uses the method defined on class B which prints B.
Initial statement
I'll start with the base code, I have adapted it to run in LINQPad (I did also change it to Write instead of WriteLine because I'll not preserve the new lines in the explanation anyway).
class A
{
public A()
{
this.Display();
}
public virtual void Display()
{
Console.Write("A"); //changed to Write
}
}
class B :A
{
public override void Display()
{
Console.Write("B"); //changed to Write
}
}
static void Main()
{
A a = new B();
a.Display();
}
The output is:
BB
In your initial question you said you were expecting:
AB
Whats happening here (as Szymon attempted to explain) is that you are creating an object of type B and the class B overrides the method Display of the class A. So whenever you call Display on that object it will be the method of the derived class (B), even from the constructor of A.
I will go over all the cases you mention. I want to encourage to read it carefully. Also, be open minded because this does not match what happens in certain other languages.
1) On override of Display method in the derived class
This is the case where you are overriding the method, ie:
public override void Display()
{
Console.Write("B"); //changed to Write
}
When you override, for all practical uses the method that will be used is the method of the derived class. Think of override as replace.
Case 1:
A a = new A(); // ---> AA
We are ok, with that.
Case 2:
B a = new B(); // ---> BB // I expect AB.
As mentioned above, calling Display on the object will always be the method on the derived class. So, both calls to Display yield B.
Case 3:
A a = new B(); // ---> BB // I expect AB.
This is a variant of the same confusion. The object is clearly of type B, even if you have it in a variable of type A. Remember that in C# the type is a property of the of the object not of the variable. So, the result is the same as above.
Note: You can still use base.Display() to access the method that was replaced.
2) Using the NEW keyword in the Display method in derived class
This is the case where you are hiding the method, ie:
public new void Display()
{
Console.Write("B"); //changed to Write
}
When you hide the method, it means that the original method is still available. You can think of it as a different method (that happens to have the same name and signature). That is: the derived class is not replacing overriding that method.
Because of that, when you do a (virtual) call to the object where at compile time it was decided it was going to use the method of the base class... the method of the derived class is not taken into consideration (in practice, it acts as it weren't a virtual call).
Think of it like this: if you call the method using a varible of the base class... the code is not aware that there exists a derived class that hides the method and that that particular call may be executed with one of those object. Instead, it will use the method of the base class, regardless.
Case 1:
B a = new B(); // ---> AB // I Expect AA here.
You see, at compile time the call in the constructor was set to use the method of the base class. That one gives A. But since the variable is of type B the compiler is aware that the method was hidden for the second call.
Case 2:
A a = new B(); // ---> AA
Here, neither in the constructor nor in the second call it will use the new method. It is not aware of it.
Case 3:
A a = new A(); // ---> AA
And I think this one is clear.
3) Using base.Display()
This the variant of the code where you do this:
public new void Display()
{
base.Display();
Console.Write("B"); //changed to Write
}
base.Display() is gonna be the method in the base class (A), no matter what.
Further reading
You said you want to learn how this works internally.
You can go deeper by reading Microsoft's C# Spec on Virtual Methods
Then read Eric Lippert's Implementing the virtual method pattern in C# (part 1, part 2 and part 3)
You may also be interested:
Anders on virtual calls from constructors.
Eric Lippert's Why Do Initializers Run In The Opposite Order As Constructors? (part 1 and part 2)
Others explanations of Virtual Methods from the web:
What's the difference between override and new? (msdn.com)
C# Virtual (dotnetpearls.com)
Understanding virtual, override and new keyword in C# (dotnet-tricks.com)
Understanding C#: Using virtual and override (oreilly.com)
You may be confusing yourself by naming the class a while instantiating it as class B. If you are looking to call the virtual method you could use the base keyword. The following code writes A B
class A
{
public A()
{
//this.Display();
}
public virtual void Display()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Display()
{
base.Display();
Console.WriteLine("B");
}
}
class C
{
static void Main(string[] args)
{
A a = new B();
a.Display();
Console.WriteLine();
Console.ReadLine();
}
}
Also note you can see why your code is displaying B B by setting a breakpoint at the beginning and then walking through your code execution line-by-line (F11).
What I understood is , in case of virtual method, same method slot is shared among the parent and child object.
If so, then I think when an object virtual method is called , by somehow compiler updates the method slot with appropriate method address so that exact method is jitted and executed In c#.
There are many classes A, B, C and so on.
In each of them, there are some methods:
class A {
void a1() { ...; }
void a2() { ...; }
}
class B { //dll
void b1() { ...; }
void b2() { ...; }
}
class C { //dll
void c1() { ...; }
void c2() { ...; }
}
Class A is coded by me and the Class B and C are an imported dll.
With Class A I can put breakpoints to track, but I can't with Class B anc C.
My program is going to be of hundreds of classes and I'd like to track in what sequential order
methods in each class are called.
Is it possible to output this kind of information even there are methods defined in dll?
Ex. a1 -> b2 -> c1 -> a2
Added:
Especially when a dll method call another dll method.
In this case wrapper would be little help.
Anyone?
If the code comes to you in a DLL with no source or debug symbols, your debug options are rather limited: you cannot set breakpoints with no source, unless you are comfortable looking at disassembly.
One way to address the issue is to wrap the external code in your own class, like this:
class CWrap {
private readonly C wrapped = new C();
public void c1() {
log.Info("Entering c1");
wrapped.c1();
log.Info("Entering c1");
}
public void c2() {
log.Info("Entering c2");
wrapped.c2();
log.Info("Exiting c2");
}
}
Mutltithreading is applied to Methods, not Classes.
Once you start the threads, order is indeterminate. Thread order execution
var a = new A();
var b = new B();
var c = new C();
new Thread(a.a1).Start();
new Thread(b.b1).Start();
new Thread(c.c1).Start();
There is no definite order for a1, b1, c1.
If you like you can pipeline the execution using Tasks .
Tasks.StartNew(()=> a.a1()).ContinueWith(_ => b.b1().ContinueWith(_=>c.c1);
It pipelines execution of a1, b1 and c1.
It makes use of Tasks.ContinueWith
Is it possible to output this kind of information even there are methods defined in dll?
Yes, if you specify debug build
I just stumbled over a very interesting problem. Giving the following code:
using System;
class Program
{
class A { }
class B : A { }
private static void MyMethod(A a) /* first method */
{
Console.WriteLine("A"); ;
}
private static void MyMethod(B b) /* second method */
{
Console.WriteLine("B");
}
static void Main(string[] args)
{
var a = new A();
// Call first method
MyMethod(a);
A b = new B();
// Should call the second method
MyMethod(b);
Console.ReadLine();
}
}
I would expect that the second method will be called because the runtime type of the variable is B. Any ideas why the code calls the first method instead?
Thanks,
Tibi
Some clarifications: Polymorphism means several forms which has nothing to do where you declare the method.
Method overloading is a form of polymorphism, ad-hoc polymorphism.
The way polymorphism is normally implemented by using late binding.
dynamic is the workaround for this problem.
The fact is that this is not working in C#(or Java) it is a design decission which I would like to understand why was made, and none of the answers is answering this question.
/Tibi
This isn't an example of polymorphism at all. Polymorphism comes in to play when you call methods ON the object, not when the object is used as a parameter. This is just a simple example of method overloading.
You declared b as being of type A, so the compiler is going to link to the overload that uses type A. The linker doesn't care that B is a subclass of A, it just picks the overload with the closest signature to the declared types (not the actual types) of the parameters passed in.
if you want to force it to use the 2nd method, cast b in to type B in the method call.
MyMethod((B)b);
Method overloading in C#, by default, is determined statically at compile time. Since you are passing a statically typed variable of type A, it will statically bind to method with the A overload. Use the dynamic keyword to get the behavior you want.
static void Main(string[] args)
{
dynamic d = new A();
// Call first method
MyMethod(d);
d = new B();
// Call the second method
MyMethod(d);
Console.ReadLine();
}
It's not calling the second method because the reference to b itself is of type A. While b contains a reference to an instance of B, that is not an actual type of B, so the overload that uses an A reference is chosen.