I am a bit confused about the virtual/new/override thing. Here's an example:
class A
{
public virtual void mVVirtual() { Console.WriteLine("A::mVVirtual"); }
}
class B : A
{
public virtual void mVVirtual() { Console.WriteLine("B::mVVirtual"); }
}
class C : B
{
public override void mVVirtual() { Console.WriteLine("C::mVVirtual"); }
}
class Test
{
static void Main()
{
B b1 = new C();
b1.mVVirtual(); //C::mVVirtual ... I understand this
A a2 = new C();
a2.mVVirtual(); //A::mVVirtual ... ???
}
}
I don't get why in the second call we get A::mVVirtual. I usually treat these issues with this "algorithm":
Check the type of the variable holding the reference for the object for an instance method called mVVirtual? Doesn't have one...but does have a virtual method with that signature and name!
Virtual method? Let's then check the type of the object being held by a2 (C) for an overriding of that method. It has one -> Executes C::mVVirtual!
Where is my "algorithm" wrong? I really am confused by this, and would greatly appreciate some help.
Here's how you think of virtual methods. Every instance of a class has "boxes" to hold methods. When you mark a method as virtual it says make a new "box" and put a method in it. When you mark a method as override in a derived class, it keeps the "box" from the base class but puts a new method in it.
So here you have a class A and a method named mVVirtual that is marked as virtual. This says make a new "box" named mVVirtual and put a method in it with definition
Console.WriteLine("A::mVVirtual");
Then you have a derived class B and a method named mVVirtual that is marked as virtual. This says make a new "box" named mVVirtual and put a method in it with definition
Console.WriteLine("B::mVVirtual");
In particular, the "box" inherited from A is hidden! It can not be seen by objects that are typed as Bs or classes that derive from B.
Then you have a derived class C and a method named mVVirtual that is marked as override. This says take the "box" named mVVirtual inherited from B and put a different method in it with definition
Console.WriteLine("C::mVVirtual");
Now, when you have
B b1 = new C();
b1.mVVirtual();
you are telling the compiler that b1 is a B so that b1.mVVirtual() looks in the "box" mVVirtual and finds the method with definition
Console.WriteLine("C::mVVirtual");
because b1 is really a C and that is what is in the "box" mVVirtual for instances of C.
But when you have
A a2 = new C();
a2.mVVirtual();
you are telling the compiler that a2 is an A and so it looks in the "box" and finds
Console.WriteLine("A::mVVirtual");
The compiler can not know that a2 is really a C (you've typed it as an A) so it does not know that a2 is really an instance of a class that is derived from a class that has hidden the "box" mVVirtual defined by A. What it does know is that A has a "box" named mVVirtual and so it emits code to invoke the method in that "box".
So, to try to put this succinctly:
class A {
public virtual void mVVirtual() { Console.WriteLine("A::mVVirtual"); }
}
defines a class that has a "box" with full name A::mVVirtual but that you can refer to by the name mVVirtual.
class B : A
{
// "new" method; compiler will tell you that this should be marked "new" for clarity.
public virtual void mVVirtual() { Console.WriteLine("B::mVVirtual"); }
}
defines a class that has a "box" with full name B::mVVirtual but that you can refer to by the name mVVirtual. Referring to B.mVVirtual will not refer to the "box" with full name A::mVVirtual; that "box" can not be seen by objects that are typed as Bs (or classes that derive from B).
class C : B
{
public override void mVVirtual() { Console.WriteLine("C::mVVirtual"); }
}
defines a class that takes the "box" with full name B::mVVirtual and puts a different method in it.
Then
A a2 = new C();
a2.mVVirtual();
says that a2 is an A so that a2.mVVirtual looks in the "box" with full name A::mVVirtual and invokes the method in that "box". This is why you see
A::mVVirtual
on the console.
There are two other method annotaters. abstract makes a new "box" does not put a method definition in the "box". new makes a new "box" and puts a method definition in the "box" but does not allow derived classes to put their own definitions of the method in the "box" (use virtual if you want to do that).
Sorry for being long-winded but I hope that helps.
UPDATE : For a more information about this language feature, see the follow-up question here: More about Virtual / new...plus interfaces!
Jason's answer is correct. To sum it up a bit more succinctly.
You have three methods. Call them MA, MB and MC.
You have two "boxes", or, as they're usually called, slots. We'll stick with Jason's nomenclature. Call them BOX1 and BOX2.
"A" defines BOX1.
"B" defines BOX2.
"C" defines no box; it reuses BOX2.
When you say "new A()", BOX1 is filled in with MA.
When you say "new B()", BOX1 is filled in with MA and BOX2 is filled in with MB.
When you say "new C()", BOX1 is filled in with MA and BOX2 is filled in with MC.
Now suppose you have a variable of type A, and a call to the method. Reason like the compiler. The compiler says "are there any boxes on type A that match this name?" Yes, there is one: BOX1. Therefore, the compiler generates a call to the contents of BOX1.
As we've seen, the contents of BOX1 is always MA, so MA is always called no matter whether the variable is actually holding a reference to A, B, or C.
Now suppose you have a variable of type B, and a call to the method. Again, think like the compiler. The compiler says "are there any boxes on type B that matches this name?" Yes, there are TWO boxes that match by name. The compiler says "which of those two is more closely associated with B?" The answer is BOX2, because B declares BOX2. Therefore, the compiler generates a call to BOX2.
This will call MB if the variable contains a B, because in a B, BOX2 contains MB. This will call MC if the variable contains a C, because in a C, BOX2 contains MC.
Is that now clear? Remember, overload resolution just chooses the box. What the contents of the box are depend upon the object at runtime.
Do you have warnings hidden? When I do what you've done, I get this warning:
'ProjectName.ClassName.B.mVVirtual()' hides inherited member 'ProjectName.ClassName.A.mVVirtual()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
If you used override in class B, you wouldn't have this problem; both cases would give you "C::mVVirtual". Since you're not using override in class B, there's an implicit new in front of the method. This breaks the inheritance chain. Your code is calling a method on type A, and there are no inheriting classes that override that method due to the implicit new. So it has to call class A's implementation.
Best way to think of it is that virtual methods use the actual (or concrete) type of the object to decide what implementation to execute, where non-Virtual methods use the 'declared type of the variabe you are using to access the method to decide which to run...
Override means you are writing a method that is going to 'replace' the implementation for a virtual or abstract method (with the same name/signature) higher up the inheritance chain.
new is used when there is a non-virtual method up the chain with the same name/signature, which the method you are adding will replace...
The difference is as follows
class base { public virtual void foo() { Console.write("base.foo"); } }
class derived { public override void foo() { Console.write("derived.foo"); } }
base b = new base();
b.foo() // prints "base.foo" // no issue b is a base and variable is a base
base b = new derived();
b.foo(); // prints "derived.foo" because concrete tyoe is derived, not base
but
class base { public void foo() { Console.write("base.foo"); } }
class derived { public new void foo() { Console.write("derived.foo"); } }
base b = new base();
b.foo() // prints "base.foo" // no issue b is a base and variable is a base
base b = new derived();
b.foo(); // prints "base.foo" because variable b is base.
derived d = b as derived;
d.foo() // prints "derived.foo" - now variable d is declared as derived.
Your second call prints A::mvVirtual because that method (mVVirtual) is actually not virtual, (in spite of it's name), because it has the new specifier... So it decides based on the variable type, which is A.
To explain what is going on technically, Every Type has a "method Table" with pointers to all the methods in that type. (It is NOT the instance of a type that has this table, It is the TYPE itself.) Each Types' method table is structured with all acessible virtual methods first, from object (furthest up the inheritance chain) at the beginning, to the virtual methods declared in the type itself, at the end. Then, after all the virtual methods are represented, all the non-virtual methods are added, again, from any non-virtual methods in object, first, all the way to any non-virtual methods in the Type itself. The table is structured this way so that the offsets for all virtual metods will be identical in all derived classes' method tables, since the compiler may call these methods from variables declared as other types, even from code in other methods declared and implemented in base types of the concrete class.
When the compiler resolves a virtual method call it goes to the method table for the Type of the object itself, (the concrete type), whereas for a non-virtual call it goes to the method table for declared type of the variable. So if you call a virtual method, even from code in a base type, if the actual concrete type is Type derived from this base type, the compiler goes to the method table for that concrete type.
If you call a non-virtual method, (no matter how far down the inheritance change the actual object's type might be), The compiler access the method table for the variab;es' declared type. This table has nothing in from any derived types furthur down the chain.
This is how I understand it
A is the base class
B inherit A but doesn't override it
C inherit B but does override it
Since you are declaring A but initialize C, it will ignore the override because the base class is A and A never get overridden from B.
Related
I am wondering if possible to override a method from calling console app or a super super class? I understand I can override WriteLog at DoMath.... however consider that I would like to manage this instead at the console app.
Example:
public class LogThings
{
public virtual void WriteLog(string value)
{
Console.WriteLine("This is the base in LogThings " + value);
}
}
The class inheriting the base. I kind of thought if I add the method again and mark it with new to implement as a virtual, then I can override this in the console app that inherits DoMath?
public class DoMath : LogThings
{
public double DoAddition(double a, double b)
{
double result;
result = a + b;
WriteLog(result.ToString()); // < the operation I need to overload
return result;
}
public new virtual void WriteLog(string value)
{
Console.WriteLine("this is overriding the base in DoMath");
base.WriteLog(value);
}
}
Some console app using the doMathANdLog class library:
class Program : DoMath
{
static void Main(string[] args)
{
var m = new DoMath();
m.DoAddition(1, 2);
Console.ReadLine();
}
public override void WriteLog(string value)
{
Console.WriteLine("this is not overriding.");
}
}
Result is this when running it:
this is overriding the base in DoMath
This is the base in LogThings 3
Is there a way to do this?
That's a simultaneously fun and annoying problem to have! :) I believe that one of the missing links here is this:
The override modifier is related to virtual or abstract methods; a method with an override modifier simply provides an alternative implementation to an existing virtual or abstract method. A virtual method has a default implementation, an abstract method has no implementation at all.
The new modifier however can be applied to any method and simply allows the reuse of a name that was already taken. These methods are not related to each other at all, the only similarity being that they forcibly share the same name.
The problem with new is that the type using a new method "pretends" that the original implementation never existed. The base class however is absolutely unaware of this - new severs the link in the hierarchy, and this is what's casing your problem.
Generally speaking, you do not want to use the new modifier.
That, and you probably wanted to use var m = new Program(); instead - reasons being explained below.
Consider these two pieces of code:
LogThings a = new DoMath();
a.WriteLog("something");
and
LogThings a = new Program();
a.WriteLog("something");
At this point, the method being called is LogThings.WriteLog(). Even though we instantiate a DoMath or Program class that provides a new method, the LogThings part of the world doesn't "know" that. It instead believes to have a virtual method that doesn't happen to be overridden. As a result, this code prints:
This is the base in LogThings something
As mentioned above: new severs that link.
In the next example, the method being called is indeed DoMath.WriteLog(), because we're now simply instantiating the DoMath() class and call its LogThings method.
DoMath b = new DoMath();
b.WriteLog("something");
Not surprisingly, this code prints
this is overriding the base in DoMath
This is the base in LogThings something
Note that it does not print "this is not overriding" because we did not instantiate an instance of the Program class. Likewise, the base.LogThings() call has nothing to do with "overriding", it simply changes the focus to the LogThings type and calls whatever implementation it knows.
This is similar to the original code you used:
var m = new DoMath();
Lastly, consider this version:
DoMath c = new Program();
c.WriteLog("something");
Here, the Program class actually overrides the virtual void WriteLog method of DoMath. Consequently, this code prints
this is not overriding.
... which is now wrong, because it does.
The key to understanding this is that each class containing virtual or abstract methods has what's called a virtual function table, or vtable. This vtable is "inherited" by derived classes and allows the compiler to know which implementation of a method to call (through a so-called virtual dispatch).
You can consider an entry in the vtable to be something like a pointer to the actual implementation of a method (the one from the current class), followed by a pointer to the previous implementation.
In your example of DoMath and Program, instantiating the DoMath class would produce a vtable consisting of only
DoMath.WriteLog(string) -> null
whereas instantiating the Program class would produce an entry like this:
Program.WriteLog(string) -> DoMath.WriteLog(string) -> null
This is why ((DoMath)new Program()).WriteLog() works - even though we look at a DoMath reference, the compiler looks up the vtable for the instantiated type (Program) and can follow the chain up to the actual implementation (Program.WriteLog).
Do however note the makeshift null in there. Because the DoMath class declares the WriteLog method as new, it is considered to be a - well - new method, which is unrelated to the one from LogThings. For LogThings, the vtable world still looks somewhat like this:
LogThings.WriteLog(string) -> null
Because there is no legit override - just a different method that happens to have the same name - ((LogThings)new Program()).WriteLog() calls LogThings.WriteLog(), as that's the last implementation in the chain. The new essentially "forces in" another vtable, resulting in this somewhat split-brained setup.
Please note that this description of a vtable is drastically oversimplified; there's plenty of good material out there on that topic however.
As noted in the comments, DoMath provides a new implementation (it's in the definition there) of the WriteLog method. Your Program class then overrides that implementation.
Where it's 'failing' is here:
var m = new DoMath();
You're not creating an instance of Program with its overridden method, so that override is never used. Try new Program() instead.
Consider the int a variables in these classes:
class Foo {
public int a = 3;
public void addFive() { a += 5; System.out.print("f "); }
}
class Bar extends Foo {
public int a = 8;
public void addFive() { this.a += 5; System.out.print("b " ); }
}
public class test {
public static void main(String [] args){
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
}
}
I understand that the method addFive() have been overridden in the child class, and in class test when the base class reference referring to child class is used to call the overridden method, the child class version of addFive is called.
But what about the public instance variable a? What happens when both base class and derived class have the same variable?
The output of the above program is
b 3
How does this happen?
There are actually two distinct public instance variables called a.
A Foo object has a Foo.a variable.
A Bar object has both Foo.a and Bar.a variables.
When you run this:
Foo f = new Bar();
f.addFive();
System.out.println(f.a);
the addFive method is updating the Bar.a variable, and then reading the Foo.a variable. To read the Bar.a variable, you would need to do this:
System.out.println(((Bar) f).a);
The technical term for what is happening here is "hiding". Refer to the JLS section 8.3, and section 8.3.3.2 for an example.
Note that hiding also applies to static methods with the same signature.
However instance methods with the same signature are "overridden" not "hidden", and you cannot access the version of a method that is overridden from the outside. (Within the class that overrides a method, the overridden method can be called using super. However, that's the only situation where this is allowed. The reason that accessing overridden methods is generally forbidden is that it would break data abstraction.)
The recommended way to avoid the confusion of (accidental) hiding is to declare your instance variables as private and access them via getter and setter methods. There are lots of other good reasons for using getters and setters too.
It should also be noted that: 1) Exposing public variables (like a) is generally a bad idea, because it leads to weak abstraction, unwanted coupling, and other problems. 2) Intentionally declaring a 2nd public a variable in the child class is a truly awful idea.
From JLS
8.3.3.2 Example: Hiding of Instance Variables This example is similar to
that in the previous section, but uses
instance variables rather than static
variables. The code:
class Point {
int x = 2;
}
class Test extends Point {
double x = 4.7;
void printBoth() {
System.out.println(x + " " + super.x);
}
public static void main(String[] args) {
Test sample = new Test();
sample.printBoth();
System.out.println(sample.x + " " +
((Point)sample).x);
}
}
produces the output:
4.7 2
4.7 2
because the declaration of x in class
Test hides the definition of x in
class Point, so class Test does not
inherit the field x from its
superclass Point. It must be noted,
however, that while the field x of
class Point is not inherited by class
Test, it is nevertheless implemented
by instances of class Test. In other
words, every instance of class Test
contains two fields, one of type int
and one of type double. Both fields
bear the name x, but within the
declaration of class Test, the simple
name x always refers to the field
declared within class Test. Code in
instance methods of class Test may
refer to the instance variable x of
class Point as super.x.
Code that uses a field access
expression to access field x will
access the field named x in the class
indicated by the type of reference
expression. Thus, the expression
sample.x accesses a double value, the
instance variable declared in class
Test, because the type of the variable
sample is Test, but the expression
((Point)sample).x accesses an int
value, the instance variable declared
in class Point, because of the cast to
type Point.
In inheritance, a Base class object can refer to an instance of Derived class.
So this is how Foo f = new Bar(); works okay.
Now when f.addFive(); statement gets invoked it actually calls the 'addFive() method of the Derived class instance using the reference variable of the Base class. So ultimately the method of 'Bar' class gets invoked. But as you see the addFive() method of 'Bar' class just prints 'b ' and not the value of 'a'.
The next statement i.e. System.out.println(f.a) is the one that actually prints the value of a which ultimately gets appended to the previous output and so you see the final output as 'b 3'. Here the value of a used is that of 'Foo' class.
Hope this trick execution & coding is clear and you understood how you got the output as 'b 3'.
Here F is of type Foo and f variable is holding Bar object but java runtime gets the f.a from the class Foo.This is because in Java variable names are resolved using the reference type and not the object which it is referring.
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#.
Ok, so I've come across this code snippet:
class1 a = new class1();
a.Test();
class1 b = new class2();
b.Test();
It had something to do with virtual and override, but my question now is:
Why type
class1 b = new class2();
when you could just type
class2 b = new class2();
because both solutions have the same output
class1 is obviously a super class of class2. That way you can for instance have a list of class1 objects, all containing either class1 or class2 objects. You could simply add a and b to that list without problems.
class Class1 {
public virtual void test(){
//do something
{
}
class Class2 : Class1 {
public override void test(){
// do something else
}
}
IList<Class1> list = new List<Class1>();
Class1 a = new Class1();
Class1 b = new Class2();
list.add(a);
list.add(b);
Then, trying to get an item from that list, you can simply do:
list[0].test(); //calls test of Class1
list[1].test(); //calls test of Class2
That concept is called polymorphism (poly=many, morph=shape).
A derived class using the "new" keyword on a method instead of "override" will behave differently depending on how it is cast.
Example:
class Class1
{
public virtual void DoSomething
{
Console.WriteLine("Class1.DoSomething");
}
}
class Class2 : Class1
{
public new void DoSomething
{
Console.WriteLine("Class2.DoSomething");
}
}
class Class3 : Class1
{
public override void DoSomething
{
Console.WriteLine("Class3.DoSomething");
}
}
Classes 2 and 3 derive from class 1, but class 2 uses the 'new' keyword to 'hide' the virtual member of class 1, while class 3 uses the 'override' keyword to 'override' the virtual member of class 1. Here is what happens when you use these classes under the guise of their own types:
Class1 one = new Class1();
one.DoSomething(); // outputs "Class1.DoSomething"
Class2 two = new Class2();
two.DoSomething(); // outputs "Class2.DoSomething"
Class3 three = new Class3();
three.DoSomething(); // outputs "Class3.DoSomething"
They all output the right class name, as expected. But this is what happens when you use these classes under the guise of class 1:
Class1 one = new Class1();
one.DoSomething(); // outputs "Class1.DoSomething"
Class1 two = new Class2();
two.DoSomething(); // outputs "Class1.DoSomething"
Class1 three = new Class3();
three.DoSomething(); // outputs "Class3.DoSomething"
Because class 2 'hides' the method, it will output 'Class2.DoSomething' when used as its own type, but it will output 'Class1.DoSomething' when used as its base type. But because class 3 'overrides' the method, it will output 'Class3.DoSomething' whether it is used as its own type or the base type -- because it 'overrides' the base type's functionality.
(The other effect of this is that if Class2 or Class3 have an additional method, say DoSomethingElse, you won't be able to call Class1 two = new Class2(); two.DoSomethingElse() because Class1 does not have that method.)
I don't know of any real-world use cases for this, but it's there, and it's the only way I can think of that using Class1 class2 = new Class2() would offer any real use. If Class2 does not 'hide' any members of Class1, then there is no real benefit.
See: http://msdn.microsoft.com/en-us/library/ms173153.aspx
Lets say, B1 and B2 both derive from A. Then you might not know until runtime whether you have a B1 or a B2. In that case you must statically generalize to A which can accommodate both subtypes. If inheritance is used correctly you don't care what the concrete runtime type is.
Example:
A a = GetA();
A GetA() {
if (Random()) return new B1();
else return new B2();
}
Because it can be both B1 and B2, you must use a common base class for the variable type (A).
It is a question of abstraction and loose coupling. If the code only depends on the type of 'class1' and not the particulars of 'class2' (which is a specific subclass of class1), then the code is more general, and you can easily switch to a different subtype of class1 without changing other code.
An example: Say you have an abstract List class. It has two subclasses, ArrayList and LinkedList. They work more or less the same (as a list of items) but are implemented differently giving them different performance characteristics. When you write your code, you are not sure which implementation is most appropriate for your code. So you want to write your code in such a way that you don't depend on the particulars of any of the specific subclasses.
If your code only cares that the class is a List, then you would only need to name the concrete subclass once:
List x = new LinkedList();
Everywhere else, you can treat it as the more general List class. This ensures two things:
If you decide to use ArrayList insted of LinkedList, you only need to change code in one place.
You don't accidentally come to depend on implementation specific details of one of the concrete subclasses, e.g. by calling a method which only exist on one of them. By casting to the base class, the type checker ensures that you only can call methods shared by all subclasses. Which again means you can easier swap implementation.
For example, List will define some methods and properties like say Count and Item, which will then be supported by all subclasses. But the specific subclasses might also define additional methods, like say Resize for ArrayList and IsCircular for LinkedList, which only makes sense for the specific subclass.
By declaring the variable as the more general type, List, you ensure that you don't come to depend on some of the subclass-specific methods or properties, since the compiler will simple not let you use them.
This is called Polymorphism. In short, it allows you to create multiple subclasses and treat them as they were the parent class, this has some advantages like preventing code duplication.
I'll add another answer to address the question why someone, in his right mind, would have typed it exactly like that.
The only case where this might behave differently is if class2 and class1 both have a method with the same name, but do not use virtual inheritance. This can be done with the new keyword (or no keyword at all which will compile but trigger a well-deserved warning).
This is bad style and almost never useful. That is probably not what he intended.
It might still make sense to write it that way to document the fact that only members of class1 are being used. He might be saying that the fact that it really is a class2 at runtime does not play a role. This is most likely because of virtual inheritance.
So this might be purely for documentation of intent.
I can explain the situation in Java, The same can be applicable in C#
From the below Code, I have created an Object (obj) referencing World class.
Since World extends both India & Belgium classes, We can make use of same Object (obj) in accessing methods of both the Classes, This kind of notation is to improve Efficiency in the code.
It is not Mandatory either to follow the same Notation.
Hope I have answered your question, Let me know in case of any concerns :)
class World {
public void printName() {
System.out.println("Name is: World");
}
}
class India extends World {
public void printName() {
System.out.println("Name is: India");
}
}
class Belgium extends World {
public void printName() {
System.out.println("Name is: Belgium");
}
}
public class Geography {
public static void main(String[] args){
World obj; // Declaring an Object referencing World Super Class
obj = new India(); // Allocating M/m to India class (All V & M Ind & World Class)
obj.printName();
// Allocating Same Object M/m to Belgium class (All V & M BGM & World Class)
obj = new Belgium();
obj.printName();
}
}
You can use this example of instatiating in the "Factory" pattern. That is the first usage which I can think of.
Was looking at some code in our codebase and I'm unable to understand how/why this is even working (and not causing a stackoverflow due to infinite recursion). I have pasted some equivalent code below:
We have a virtual method Foo(B) defined in class P1 and overridden in class P2. P2 also defines a private non-virtual method Foo(A). B derives from A. P2::Foo(B) has a call in the end: Foo(b). I expect this to end up in a stack overflow.
However, the output is:
P2::Foo Virtual
P2::Foo Private Non-Virtual
Looks like the second call to Foo in the overridden method is picking up the non-virtual method Foo in this case. On doing similar operations in P1 (uncomment code), we end up calling Foo infinite number of times through recursion.
Questions: (finally!)
1. Why is the behavior different in the original virtual method and the overridden method? Why is one calling itself and the other calling a different method?
2. Is there an order of preference specified somewhere? Note that if we change the private modifier to public, in both cases, we end up calling the non-virtual method (Even if we instantiate P2 this way: P1 p2 = new P2(); , instead of P2 p2 = new P2();) It looks like the non-virtual version is preferred, except when it is inside a virtual method definition. Is this true?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class P1
{
static void Main(string[] args)
{
B b = new B();
P2 p2 = new P2();
p2.Foo(b);
// Uncomment code to cause infinite recursion
//P1 p1 = new P1();
//p1.Foo(b);
}
private void Foo(A a)
{
Console.WriteLine("P1::Foo Private Non-Virtual");
}
public virtual void Foo(B b)
{
Console.WriteLine("Inside P1::Foo");
// Uncomment code to cause infinite recursion
// Foo(b);
}
}
public class P2 : P1
{
private void Foo(A a)
{
Console.WriteLine("P2::Foo Private Non-Virtual");
}
public override void Foo(B b)
{
Console.WriteLine("P2::Foo Virtual");
Foo(b);
}
}
public class A
{
public int a = 10;
}
public class B : A
{
public int b = 20;
}
}
This is because overload resolution only looks at inherited members if it cannot select an overload defined on the derived type. From the spec (version 4):
For example, the set of candidates for a method invocation does not include methods marked override (§7.4), and methods in a base class are not candidates if any method in a derived class is applicable (§7.6.5.1).
To address your questions specifically:
Why is the behavior different in the original virtual method and the overridden method?
Because the overridden method is defined in a derived class, and an applicable overload exists in that class, the virtual method is not considered. The overriding method is not considered, because overrides are never considered.
Why is one calling itself and the other calling a different method?
The behavior in the derived class is explained above. In the base class, the best candidate for overload resolution is the virtual method itself, because it is more specific (B is derived from A).
Is there an order of preference specified somewhere?
Yes, in the C# Language Specification (link to the MSDN page for the Visual Studio 2012 version of the specification).
Note that if we change the private modifier to public, in both cases, we end up calling the non-virtual method (Even if we instantiate P2 this way: P1 p2 = new P2(); , instead of P2 p2 = new P2();)
Accessibility is not a significant issue in this case. The type of the variable p2 is not relevant either, because the overload resolution you're asking about concerns a call site in the P2 override of the virtual method. Virtual dispatch ensures that the call in Main() invokes the override, regardless of the static type of the variable. At the call site in P2's override void Foo(B b), the receiver is implicitly this, which always has a static type of P2.
It looks like the non-virtual version is preferred, except when it is inside a virtual method definition. Is this true?
Not quite; as explained above, the preference is not for non-virtual methods, but for methods defined in the type of the receiver (i.e., the static type of the object reference on which the method is being called).
This is a frequently misunderstood feature of C#: methods in a base class are not candidates if any method in a derived class is applicable