This question already has answers here:
Difference between shadowing and overriding in C#?
(6 answers)
Closed 3 years ago.
I am a bit confused about overriding vs. hiding a method in C#. Practical uses of each would also be appreciated, as well as an explanation for when one would use each.
I am confused about overriding - why do we override? What I have learnt so far is that by overring we can provide desired implementation to a method of a derived class, without changing the signature.
If I don't override the method of the superclass and I make changes to the method in the sub class, will that make changes to the super class method ?
I am also confused about the following - what does this demonstrate?
class A
{
virtual m1()
{
console.writeline("Bye to all");
}
}
class B : A
{
override m1()
{
console.writeLine("Hi to all");
}
}
class C
{
A a = new A();
B b = new B();
a = b; (what is this)
a.m1(); // what this will print and why?
b = a; // what happens here?
}
Consider:
public class BaseClass
{
public void WriteNum()
{
Console.WriteLine(12);
}
public virtual void WriteStr()
{
Console.WriteLine("abc");
}
}
public class DerivedClass : BaseClass
{
public new void WriteNum()
{
Console.WriteLine(42);
}
public override void WriteStr()
{
Console.WriteLine("xyz");
}
}
/* ... */
BaseClass isReallyBase = new BaseClass();
BaseClass isReallyDerived = new DerivedClass();
DerivedClass isClearlyDerived = new DerivedClass();
isReallyBase.WriteNum(); // writes 12
isReallyBase.WriteStr(); // writes abc
isReallyDerived.WriteNum(); // writes 12
isReallyDerived.WriteStr(); // writes xyz
isClearlyDerived.WriteNum(); // writes 42
isClearlyDerived.writeStr(); // writes xyz
Overriding is the classic OO way in which a derived class can have more specific behaviour than a base class (in some languages you've no choice but to do so). When a virtual method is called on an object, then the most derived version of the method is called. Hence even though we are dealing with isReallyDerived as a BaseClass then functionality defined in DerivedClass is used.
Hiding means that we have a completely different method. When we call WriteNum() on isReallyDerived then there's no way of knowing that there is a different WriteNum() on DerivedClass so it isn't called. It can only be called when we are dealing with the object as a DerivedClass.
Most of the time hiding is bad. Generally, either you should have a method as virtual if its likely to be changed in a derived class, and override it in the derived class. There are however two things it is useful for:
Forward compatibility. If DerivedClass had a DoStuff() method, and then later on BaseClass was changed to add a DoStuff() method, (remember that they may be written by different people and exist in different assemblies) then a ban on member hiding would have suddenly made DerivedClass buggy without it changing. Also, if the new DoStuff() on BaseClass was virtual, then automatically making that on DerivedClass an override of it could lead to the pre-existing method being called when it shouldn't. Hence it's good that hiding is the default (we use new to make it clear we definitely want to hide, but leaving it out hides and emits a warning on compilation).
Poor-man's covariance. Consider a Clone() method on BaseClass that returns a new BaseClass that's a copy of that created. In the override on DerivedClass this will create a DerivedClass but return it as a BaseClass, which isn't as useful. What we could do is to have a virtual protected CreateClone() that is overridden. In BaseClass we have a Clone() that returns the result of this - and all is well - in DerivedClass we hide this with a new Clone() that returns a DerivedClass. Calling Clone() on BaseClass will always return a BaseClass reference, which will be a BaseClass value or a DerivedClass value as appropriate. Calling Clone() on DerivedClass will return a DerivedClass value, which is what we'd want in that context. There are other variants of this principle, however it should be noted that they are all pretty rare.
An important thing to note with the second case, is that we've used hiding precisely to remove surprises to the calling code, as the person using DerivedClass might reasonably expect its Clone() to return a DerivedClass. The results of any of the ways it could be called are kept consistent with each other. Most cases of hiding risk introducing surprises, which is why they are generally frowned upon. This one is justified precisely because it solves the very problem that hiding often introduces.
In all, hiding is sometimes necessary, infrequently useful, but generally bad, so be very wary of it.
Overriding is when you provide a new override implementation of a method in a descendant class when that method is defined in the base class as virtual.
Hiding is when you provide a new implementation of a method in a descendant class when that method is not defined in the base class as virtual, or when your new implementation does not specify override.
Hiding is very often bad; you should generally try not to do it if you can avoid it at all. Hiding can cause unexpected things to happen, because Hidden methods are only used when called on a variable of the actual type you defined, not if using a base class reference... on the other hand, Virtual methods which are overridden will end up with the proper method version being called, even when called using the base class reference on a child class.
For instance, consider these classes:
public class BaseClass
{
public virtual void Method1() //Virtual method
{
Console.WriteLine("Running BaseClass Method1");
}
public void Method2() //Not a virtual method
{
Console.WriteLine("Running BaseClass Method2");
}
}
public class InheritedClass : BaseClass
{
public override void Method1() //Overriding the base virtual method.
{
Console.WriteLine("Running InheritedClass Method1");
}
public new void Method2() //Can't override the base method; must 'new' it.
{
Console.WriteLine("Running InheritedClass Method2");
}
}
Let's call it like this, with an instance of InheritedClass, in a matching reference:
InheritedClass inherited = new InheritedClass();
inherited.Method1();
inherited.Method2();
This returns what you should expect; both methods say they are running the InheritedClass versions.
Running InheritedClass Method1
Running InheritedClass Method2
This code creates an instance of the same, InheritedClass, but stores it in a BaseClass reference:
BaseClass baseRef = new InheritedClass();
baseRef.Method1();
baseRef.Method2();
Normally, under OOP principles, you should expect the same output as the above example. But you don't get the same output:
Running InheritedClass Method1
Running BaseClass Method2
When you wrote the InheritedClass code, you may have wanted all calls to Method2() to run the code you wrote in it. Normally, this would be how it works - assuming you are working with a virtual method that you have overridden. But because you are using a new/hidden method, it calls the version on the reference you are using, instead.
If that's the behavior you truly want, then; there you go. But I would strongly suggest that if that's what you want, there may be a larger architectural issue with the code.
Method Overriding is simpley override a default implementation of a base class method in the derived class.
Method Hiding : You can make use of 'new' keyword before a virtual method in a derived class
as
class Foo
{
public virtual void foo1()
{
}
}
class Bar:Foo
{
public new virtual void foo1()
{
}
}
now if you make another class Bar1 which is derived from Bar , you can override foo1 which is defind in Bar.
Related
I have a problem with my code.
I would expect that since I'm constructing the Implementation object; every time I call Method() I'd use actual Implementation.Method() and not it's abstract's Base.Method(). It does not seem reasonable that I have to downcast to actual implementer or specify interface explicitly (So interfaces are not transitive in C#? I will call the "first proper instance of interface implementer" and not my class?)
I have a structure similar to this (simplified for clarity):
https://dotnetfiddle.net/oYVlQO
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public string Method() { return "Sample"; }
}
public class Implementation : Base // if I add ", IBase" to this it works as expected, but why?
{
new public string Method() { return "Overriden"; }
}
public class Program
{
// and it's used like so...
public static void Main()
{
IBase b = new Implementation();
//Implementation b = new Implementation(); // It works as expected, always using Implementation.Method();
Console.WriteLine(b.Method()); // Produces "Sample", so Base.Method(). Why not implementation?
Console.WriteLine(((Implementation) b).Method()); // Produces "Overriden", so Implementation.Method(); Since when I have to downcast to use overriden method!?
}
}
}
I'm really scratching my head over this; Especially that the same code in Java works "as I would expect" https://repl.it/repls/VitalSpiritedWebpage
I've tried to find it in the c# specs to no avail, maybe I do not have the proper keywords...
In cause of the question, which is:
Why is it that way?
My answer:
Because you don’t override the method but hide it.
The interface is implemented by the baseclass, so the Method is called on the base-class.
To answer the question, which isn’t asked:
How would it work?
Answer:
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public virtual string Method() { return "Sample"; }
}
public class Implementation : Base
{
public override string Method() { return "Overriden"; }
}
You may want to take a look at the part of the C# spec that deals with interface re-implementation.
When you access a member through the interface, it begins its lookup at the most derived type that explicitly implements that interface. In your example, the most derived type is Base and so it calls the method that's present there.
When you added IBase to the list of interfaces explicitly implemented by Implementation it worked, because that's the new starting point for lookup and it finds your new method.
You can either solve your problem by making the base member virtual and then overriding it in derived classes, or you can re-implement the interface by including that in the list for your Implementation class.
So the problem in my sample code is two-fold.
I assumed that in C# methods are "virtual" by default (as is in Java). Since I'm usually coding in Java, I've made an incorrect assumption.
See Is it possible to override a non-virtual method?
If I'd use virtual, I could override the method and achieve exactly the output I expected, as described in doc:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/virtual namely "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."
My code, hovewer, is using method hiding, so unless I inform the compiler about my intention of using my implementation, it'll default to non-hidden method (as resolved by abstract class being the actual, original implementer)
I'm new to C# override and virtual. In the following example I want to call Callee method in B class from Caller method in A class. B inherits A. Any thoughts?
namespace Blah
{
public class Program
{
public static void Main(string[] args)
{
A a = new A();
a.Caller();
}
}
class A
{
public void Caller()
{
Console.WriteLine("In Caller");
Callee(); // How to make this call B:Callee() and make it print "in B"
}
public virtual void Callee()
{
Console.Write("In A");
}
}
class B : A
{
public override void Callee()
{
Console.Write("In B");
}
}
}
If you want to call the Callee method inside class B, you have first to create an instance of this class and then call this method:
var b = new B();
B.Callee();
If that is you are looking for (despite it does not make sense from a practical prespective), you should place the above two lines inside the method Caller in class A.
Usually we define a base class and if we think that a method in the class we define can be re-implemented from classes that would be derived from our class, we mark the method as virtual. When we derive a class from our base class and we do not override the virtual method, then the method that has been defined in the base class is called. Whereas when we have overriden a virtual method defined in a base class, the method in the derived class is called.
In your example you have the baseclass A with a subclass B that overrides a method in A. This means that you create an alternative A, that can interact as an A but might have different behavior.
However, this does not mean that every instance of A suddenly starts to use this definition. In your example you create a hard instance of A, but as the overriding method is in B it will never be called.
Instead you should create an instance of B, which you can cast to an A. Allowing your code to treat it as an A object, even though its B.
In your example, the only thing you'll need to do is create an instance of B (fiddle):
A a = new B();
a.Caller();
// Prints:
// In Caller
// In B
The way this works is more or less the same as Java inheritance, only in C# you need to mark methods as virtual in order to override them.
However, if your intention was to change definition of Callee in A without having to create a B (so new A().Caller()would print out "In B"), you should rethink whatever you are trying to do. It is something completely different from virtual methods and in most situations something you should try to avoid.
Can anybody tell the working of overriding and hiding in terms of memory and references.
class A
{
public virtual void Test1() { //Impl 1}
public virtual void Test2() { //Impl 2}
}
class B : A
{
public override void Test1() { //Impl 3}
public new void Test2() { Impl 4}
}
static Main()
{
A aa=new B() //This will give memory to B
aa.Test1(); //What happens in terms of memory when this executes
aa.Test2(); //-----------------------SAME------------------------
}
Here memory is with class B but in the second statement aa.Test2 class A's method will be called. Why is it? If B has memory then B's method should be called (in my point of view).
Any link / exercise that describes this fundamental very deeply and completely will be a big help.
Take a look at this answer to a different question by Eric Lippert.
To paraphrase (to the limits of my comprehension), these methods go into "slots". A has two slots: one for Test1 and one for Test2.
Since A.Test1 is marked as virtual and B.Test1 is marked as override, B's implementation of Test1 does not create its own slot but overwrites A's implementation. Whether you treat an instance of B as a B or cast it to an A, the same implementation is in that slot, so you always get the result of B.Test1.
By contrast, since B.Test2 is marked new, it creates its own new slot. (As it would if it wasn't marked new but was given a different name.) A's implementation of Test2 is still "there" in its own slot; it's been hidden rather than overwritten. If you treat an instance of B as a B, you get B.Test2; if you cast it to an A, you can't see the new slot, and A.Test2 gets called.
To add to #Rawling's answer, practical examples could be shown using an example such as this:
class Base
{
// base property
public virtual string Name
{
get { return "Base"; }
}
}
class Overriden : Base
{
// overriden property
public override string Name
{
get { return "Overriden"; }
}
}
class New : Base
{
// new property, hides the base property
public new string Name
{
get { return "New"; }
}
}
1. Overriding
In case of the overriden property, base class' virtual method's slot is replaced by a different implementation. Compiler sees the method as virtual, and must resolve its implementation during run-time using the object's virtual table.
{
Base b = new Base();
Console.WriteLine(b.Name); // prints "Base"
b = new Overriden();
// Base.Name is virtual, so the vtable determines its implementation
Console.WriteLine(b.Name); // prints "Overriden"
Overriden o = new Overriden();
// Overriden.Name is virtual, so the vtable determines its implementation
Console.WriteLine(o.Name); // prints "Overriden"
}
2. Hiding
When a method or a property is hidden using the new keyword, the compiler creates a new non-virtual method for the derived class only; base class' method remains untouched.
If the type of the variable is Base (i.e. only contains the virtual method), its implementation will be resolved through the vtable. If the type of the variable is New, then the non-virtual method or property will be invoked.
{
Base b = new Base();
Console.WriteLine(b.Name); // prints "Base"
b = new New();
// type of `b` variable is `Base`, and `Base.Name` is virtual,
// so compiler resolves its implementation through the virtual table
Console.WriteLine(b.Name); // prints "Base"
New n = new New();
// type of `n` variable is `New`, and `New.Name` is not virtual,
// so compiler sees `n.Name` as a completely different property
Console.WriteLine(n.Name); // prints "New"
}
3. Summary
If a part of your code accepts the base type, it will always use the virtual table during run-time. For most OOP scenarios, this means that marking a method as new is very similar to giving it a completely different name.
4. Object sizes after instantiation
Note that instantiating any of these types doesn't create a copy of the virtual table. Each .NET object has a couple of bytes of header and a pointer to the virtual table of table of its type (class).
Regarding the new property (the one which is not virtual), it is basically compiled as a static method with thiscall semantics, meaning that it also doesn't add anything to the size of the instance in memory.
Already answered at here
Overriding is the definition of multiple possible implementations of the same method signature, such that the implementation is determined by the runtime type of the zeroth argument (generally identified by the name this in C#).
Hiding is the definition of a method in a derived type with a signature identical to that in one of its base types without overriding.
The practical difference between overriding and hiding is as follows:
Hiding is for all other members (static methods , instance members, static members). It is based on the early binding . More clearly , the method or member to be called or used is decided during compile time.
•If a method is overridden, the implementation to call is based on the run-time type of the argument this.
•If a method is simply hidden, the implementation to call is based on the compile-time type of the argument this.
Here are some samples : Example # 1. and Example # 2
Test1() method in class A and test1() method in class B will executes according to MethdOverriding.
Test2() method in class A and test2() method in class B will executes according to Method Hiding.
In method Overriding the child class members will execute, and in Method Hiding the Parent class members will execute.
Put simply when overriding a method or property the override method must have the same signature as the base method. When hiding this is not required, the new object can take any form as shown below
// base
public int GrossAmount { get; set; }
// hiding base
public new string GrossAmount
{
get;
set;
}
Deducting from the code provided you should have B:A.
You can hide a method in case when you want create your own implementation of the (say) method of the base class, which can not be overriden, cause, say, it's not virtual.
In my expirience, I used hiding mostly for debug purposes.
For example when I don't know who sets the property of some 3rd prt component, whom code is not available to me. So what I do is:
create a child class from the component
hide the property of interest with new keyword
put the breakpoint in set
and wait when it will be hit.
Sometimes, very useful and helps me get information in fast way, especially in first stage when you're learning new components, frameworks, libraries.. whatever.
By hiding a method or a property you are simply stating that you want to stop such method being polymorphic when you have an object of that type. Additionally hidden methods are called in a non polymorphic way so to call these method type has to be know at compile time, as it was a simply non virtual method.
public class BaseClass
{
public void PrintMethod()
{
Console.WriteLine("Calling base class method");
}
}
public class ChildClass
{
public new void PrintMethod()
{
Console.WriteLine("Calling the child or derived class method");
}
}
class Program
{
static void Main()
{
BaseClass bc = new ChildClass();
bc.PrintMethod();
}
}
Method Hiding is that when Base Class reference variable pointing to a child class object. It will invoke the hidden method in base Class.
Where as, When We declare virtual method in the base class. We override that method in the derived or child class. Then Base Class reference variable will call the derived class method. This is called Method Overriding.
class Base {
int a;
public void Addition() {
Console.WriteLine("Addition Base");
}
public virtual void Multiply()
{
Console.WriteLine("Multiply Base");
}
public void Divide() {
Console.WriteLine("Divide Base");
}
}
class Child : Base
{
new public void Addition()
{
Console.WriteLine("Addition Child");
}
public override void Multiply()
{
Console.WriteLine("Multiply Child");
}
new public void Divide()
{
Console.WriteLine("Divide Child");
}
}
class Program
{
static void Main(string[] args)
{
Child c = new Child();
c.Addition();
c.Multiply();
c.Divide();
Base b = new Child();
b.Addition();
b.Multiply();
b.Divide();
b = new Base();
b.Addition();
b.Multiply();
b.Divide();
}
}
Output : -
Addition Child
Multiply Child
Divide Child
Addition Base
Multiply Child
Divide Base
Addition Base
Multiply Base
Divide Base
At the time of overriding the compiler checks the object of the class but in
in hiding compiler only checks the reference of the class
This question already has answers here:
Difference between shadowing and overriding in C#?
(7 answers)
Closed 3 years ago.
I am a bit confused about overriding vs. hiding a method in C#. Practical uses of each would also be appreciated, as well as an explanation for when one would use each.
I am confused about overriding - why do we override? What I have learnt so far is that by overring we can provide desired implementation to a method of a derived class, without changing the signature.
If I don't override the method of the superclass and I make changes to the method in the sub class, will that make changes to the super class method ?
I am also confused about the following - what does this demonstrate?
class A
{
virtual m1()
{
console.writeline("Bye to all");
}
}
class B : A
{
override m1()
{
console.writeLine("Hi to all");
}
}
class C
{
A a = new A();
B b = new B();
a = b; (what is this)
a.m1(); // what this will print and why?
b = a; // what happens here?
}
Consider:
public class BaseClass
{
public void WriteNum()
{
Console.WriteLine(12);
}
public virtual void WriteStr()
{
Console.WriteLine("abc");
}
}
public class DerivedClass : BaseClass
{
public new void WriteNum()
{
Console.WriteLine(42);
}
public override void WriteStr()
{
Console.WriteLine("xyz");
}
}
/* ... */
BaseClass isReallyBase = new BaseClass();
BaseClass isReallyDerived = new DerivedClass();
DerivedClass isClearlyDerived = new DerivedClass();
isReallyBase.WriteNum(); // writes 12
isReallyBase.WriteStr(); // writes abc
isReallyDerived.WriteNum(); // writes 12
isReallyDerived.WriteStr(); // writes xyz
isClearlyDerived.WriteNum(); // writes 42
isClearlyDerived.writeStr(); // writes xyz
Overriding is the classic OO way in which a derived class can have more specific behaviour than a base class (in some languages you've no choice but to do so). When a virtual method is called on an object, then the most derived version of the method is called. Hence even though we are dealing with isReallyDerived as a BaseClass then functionality defined in DerivedClass is used.
Hiding means that we have a completely different method. When we call WriteNum() on isReallyDerived then there's no way of knowing that there is a different WriteNum() on DerivedClass so it isn't called. It can only be called when we are dealing with the object as a DerivedClass.
Most of the time hiding is bad. Generally, either you should have a method as virtual if its likely to be changed in a derived class, and override it in the derived class. There are however two things it is useful for:
Forward compatibility. If DerivedClass had a DoStuff() method, and then later on BaseClass was changed to add a DoStuff() method, (remember that they may be written by different people and exist in different assemblies) then a ban on member hiding would have suddenly made DerivedClass buggy without it changing. Also, if the new DoStuff() on BaseClass was virtual, then automatically making that on DerivedClass an override of it could lead to the pre-existing method being called when it shouldn't. Hence it's good that hiding is the default (we use new to make it clear we definitely want to hide, but leaving it out hides and emits a warning on compilation).
Poor-man's covariance. Consider a Clone() method on BaseClass that returns a new BaseClass that's a copy of that created. In the override on DerivedClass this will create a DerivedClass but return it as a BaseClass, which isn't as useful. What we could do is to have a virtual protected CreateClone() that is overridden. In BaseClass we have a Clone() that returns the result of this - and all is well - in DerivedClass we hide this with a new Clone() that returns a DerivedClass. Calling Clone() on BaseClass will always return a BaseClass reference, which will be a BaseClass value or a DerivedClass value as appropriate. Calling Clone() on DerivedClass will return a DerivedClass value, which is what we'd want in that context. There are other variants of this principle, however it should be noted that they are all pretty rare.
An important thing to note with the second case, is that we've used hiding precisely to remove surprises to the calling code, as the person using DerivedClass might reasonably expect its Clone() to return a DerivedClass. The results of any of the ways it could be called are kept consistent with each other. Most cases of hiding risk introducing surprises, which is why they are generally frowned upon. This one is justified precisely because it solves the very problem that hiding often introduces.
In all, hiding is sometimes necessary, infrequently useful, but generally bad, so be very wary of it.
Overriding is when you provide a new override implementation of a method in a descendant class when that method is defined in the base class as virtual.
Hiding is when you provide a new implementation of a method in a descendant class when that method is not defined in the base class as virtual, or when your new implementation does not specify override.
Hiding is very often bad; you should generally try not to do it if you can avoid it at all. Hiding can cause unexpected things to happen, because Hidden methods are only used when called on a variable of the actual type you defined, not if using a base class reference... on the other hand, Virtual methods which are overridden will end up with the proper method version being called, even when called using the base class reference on a child class.
For instance, consider these classes:
public class BaseClass
{
public virtual void Method1() //Virtual method
{
Console.WriteLine("Running BaseClass Method1");
}
public void Method2() //Not a virtual method
{
Console.WriteLine("Running BaseClass Method2");
}
}
public class InheritedClass : BaseClass
{
public override void Method1() //Overriding the base virtual method.
{
Console.WriteLine("Running InheritedClass Method1");
}
public new void Method2() //Can't override the base method; must 'new' it.
{
Console.WriteLine("Running InheritedClass Method2");
}
}
Let's call it like this, with an instance of InheritedClass, in a matching reference:
InheritedClass inherited = new InheritedClass();
inherited.Method1();
inherited.Method2();
This returns what you should expect; both methods say they are running the InheritedClass versions.
Running InheritedClass Method1
Running InheritedClass Method2
This code creates an instance of the same, InheritedClass, but stores it in a BaseClass reference:
BaseClass baseRef = new InheritedClass();
baseRef.Method1();
baseRef.Method2();
Normally, under OOP principles, you should expect the same output as the above example. But you don't get the same output:
Running InheritedClass Method1
Running BaseClass Method2
When you wrote the InheritedClass code, you may have wanted all calls to Method2() to run the code you wrote in it. Normally, this would be how it works - assuming you are working with a virtual method that you have overridden. But because you are using a new/hidden method, it calls the version on the reference you are using, instead.
If that's the behavior you truly want, then; there you go. But I would strongly suggest that if that's what you want, there may be a larger architectural issue with the code.
Method Overriding is simpley override a default implementation of a base class method in the derived class.
Method Hiding : You can make use of 'new' keyword before a virtual method in a derived class
as
class Foo
{
public virtual void foo1()
{
}
}
class Bar:Foo
{
public new virtual void foo1()
{
}
}
now if you make another class Bar1 which is derived from Bar , you can override foo1 which is defind in Bar.
I'm having the following classes:
class Base
{
public virtual void Print()
{
Console.WriteLine("Base");
}
}
class Der1 : Base
{
public new virtual void Print()
{
Console.WriteLine("Der1");
}
}
class Der2 : Der1
{
public override void Print()
{
Console.WriteLine("Der2");
}
}
This is my main method:
Base b = new Der2();
Der1 d1 = new Der2();
Der2 d2 = new Der2();
b.Print();
d1.Print();
d2.Print();
The output is Base, Der2, Der2.
As far as I know, Override won't let previous method to run, even if the pointer is pointing to them. So the first line should output Der2 as well. However Base came out.
How is it possible? How the override didn't work there?
You've never actually overriden the Base version of Print(). You've only hidden it with a separate virtual method (named the same) in Der1.
When you use the new keyword on a method signature - you are telling the compiler that this is a method that happens to have the same name as a method of one of your base classes - but has no other relation. You can make this new method virtual (as you've done) but that's not the same as overriding the base class method.
In Der2 when you override Print you are actually overriding the 'new' version that you declared in Der1 - not the version is Base. Eric Lippert has an excellent answer to a slightly different question that may help you reason about how virtual methods are treated in the C# language.
In your example, when you call Print, you are calling it in the first case through a reference of type Base - so the hidden (but not overriden) version of Print is called. The other two calls are dispatched to Der1's implementation, because in this case, you've actually overriden the method.
You can read more about this in the MSDN documentation of new and override.
What you may have intended to do with Der1 (as you did with Der2) is to use the override keyword:
class Base
{
public virtual void Print()
{
Console.WriteLine("Base");
}
}
class Der1 : Base
{
// omitting 'new' and using override here will override Base
public override void Print()
{
Console.WriteLine("Der1");
}
}
It's because Der1 does not override Print, it replaces it with a brand new method that happens to have the same name (this is caused by the use of the new keyword). So, when the object is cast to Base it calls Print in Base; there is no override to call..
override will replace the previous method, but as your Der1 class doesn't override Print() (it Shadows it, to use a VB-ism), then the most overriden verion of Base's Print() is called, which happens to be the version it defines
As everyone has said the class Der1 is replacing Print() instead of overriding it. To see this in action you could base d1 and d2 to Base and then call the print method. It will then return Base.
((Base)d2).Print(); //Base