Can someone help me understand
Is this statement correct: BaseClass bcdc = new DerivedClass(); which means bcdc is of type BaseClass class, and its value is of type DerivedClass object? Also, what does that mean and why would an object be instantiated like that as opposed to having the class type be the same as the new object being instantiated, as in DerivedClass dc = new DerivedClass()?
Why bcdc.Method1() => Derived-Method1. Is it because the keyword override is used, and is so overriding the virtual Method1?
Why bcdc.Method2() => Base-Method2. I am confused because the new key word in the DerivedClass should be hiding Base-Method2? I thought that was the functionality of the new keyword.
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass(); //bc is of type BaseClass, and its value is of type BaseClass
DerivedClass dc = new DerivedClass(); //dc is of type DerivedClass, and its value is of type DerivedClass
BaseClass bcdc = new DerivedClass(); //bcdc is of type BaseClass, and its value is of type DerivedClass.
bc.Method1(); //Base - Method1
bc.Method2(); //Base - Method2
dc.Method1(); //Derived - Method1
dc.Method2(); //Derived - Method2
bcdc.Method1(); //Derived - Method1. ??
bcdc.Method2(); //Base - Method2. ??
}
} ```
which means bcdc is of type BaseClass class, and its value is of type DerivedClass object?
Yes. I would however prefer to call it a DerivedClass object with a BaseClass reference
Also, what does that mean and why would an object be instantiated like that as opposed to having the class type be the same as the new object being instantiated, as in DerivedClass dc = new DerivedClass()?
One case is when you want to call an explicit interface method. However, a very similar and more common case would happen if you call a method: MyMethod(BaseClass bcdc).
In this simple program all types are easily known at compile time. But for larger programs this would not be the case, a method take a BaseClass parameter that can have a bunch of different implementations, and all the implementations might not be known when the code is compiled.
Why bcdc.Method1() => Derived-Method1. Is it because the keyword override is used, and is so overriding the virtual Method1?
Yes, for methods marked as virtual the compiler will insert a check that forwards the method call to the overridden method based on the actual object type, i.e. DerivedClass. This is sometimes called virtual dispatch or dynamic dispatch. I.e. the method will be selected dynamically at runtime based on the object type.
Why bcdc.Method2() => Base-Method2. I am confused because the new key word in the DerivedClass should be hiding Base-Method2? I thought that was the functionality of the new keyword.
Method2 is not virtual, so there will be no dynamic dispatch. So the reference type, i.e. BaseClass, will be used to determine the called method. This is called static dispatch, i.e. the called method can be determined statically at compile time.
Related
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
In case of method overriding based on the type referent object hold method call will be decided.
In case of method hiding based on type of object method call will be decided.
Can any one explain me the method calling decision in overriding + hiding.
public class Base
{
public virtual void DoIt()
{
}
}
public class Derived : Base
{
public override void DoIt()
{
}
}
public class Derived1 : Derived
{
public new void DoIt()
{
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
Derived d = new Derived();
#1 b.DoIt(); // Calls Derived.DoIt
#2 d.DoIt(); // Calls Derived.DoIt
b = new Derived1();
d = new Derived1();
#3 b.DoIt(); // Calls Derived.DoIt
#4 d.DoIt();
}
}
#1 and #2 call Derived.DoIt because of run-time polymorphism.
#4 called Derived.DoIt because d is of type Dreived (Method hiding).
But why #3 called Derived.DoIt.
What is the calling sequence in case of overiding plus hiding in c#.
Thanks in advance
Because #3 is an instance of Base type. Here, the last derived method of Base resides in Derived class and hence it is being called.
new / method hiding / shadowing is different than method overriding in the sense that override means that you are customizing the base method whereas new means you are just providing a different implementation for the same method name.
In Method overriding it is decided on run-time which type's method to be called, but method hiding or shadowing is compile time thing, the compiler knows at compile time that which type's method is to called, when you use new keyword in derived type in method signature instead of override, that means that if you will call using reference of base class it will call base class implementation and if you use derived class reference it will call derived class method implementation.
The derived class implementation get's hidden from base class.
If you write it like this:
b = new Derived1();
b.DoIt() // (run-time) will call Dervied method implementation as Dervied has overridden
// so calling via base reference will call overridden implementation if any
//otherwise base class implementation will get called
Derived1 d1 = (Derived1)b;
d1.DoIt(); // (compile time) will call Derived1 method implementation due to hiding in Derived1
Derived d = (Derived)b;
d.DoIt(); // (run-time) will call Derived method implementation due to override
#3 calls Derived.DoIt() because the method was only hidden, it is still externally callable if using the appropriate cast. The variable b of is of type Base, and so you are accessing the methods available to Base. This is the one that is overwritten via Derived, so your result is the one from Derived.DoIt. Would you have a variable of type Derived1 and did a call to DoIt there, Derived1.DoIt would have been called instead.
public class Base
{
public virtual void DoIt()
{
Console.WriteLine("Base.DoIt was called!");
}
}
public class Derived : Base
{
public override void DoIt()
{
Console.WriteLine("Derived.DoIt was called!");
}
}
public class Derived1 : Derived
{
public new void DoIt()
{
Console.WriteLine("Derived1.DoIt was called!");
}
}
class Program
{
static void Main(string[] args)
{
Base b = new Derived();
Derived d = new Derived();
Console.WriteLine("#1");
b.DoIt();
Console.WriteLine("#2");
d.DoIt();
b = new Derived1();
d = new Derived1();
Console.WriteLine("#3");
b.DoIt();
Console.WriteLine("#4");
d.DoIt();
Console.WriteLine("#5");
Derived1 e = new Derived1();
e.DoIt();
Console.ReadKey();
}
}
In "The C# Programming Language" book Eric Lippert mentioned this:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it.
What is the significance of this statement? Why does it matter if the overridden virtual method is considered to be a method of the class that introduced it (or otherwise) since the overridden method will never be called unless you are dealing with the derived class?
It matters when you have a reference of one type pointing to an object of a different type.
Example:
public class BaseClass {
public virtual int SomeVirtualMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public override int SomeVirtualMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeVirtualMethod(); // will be 2
Because the virtual method is a member of the base class, you can call the overriding method with a reference of the base class type. If it wasn't, you would need a reference of the derived type to call the overriding method.
When you are shadowing a method instead of overriding it, the shadowing method is a member of the derived class. Depending on the type of the reference you will be calling the original method or the shadowing method:
public class BaseClass {
public int SomeMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public new int SomeMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeMethod(); // will be 1
DerivedClass ref2 = ref;
int test2 = ref2.SomeMethod(); // will be 2
Here's the full quote from the book:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it. The overload resolution rules in some cases prefer members of more derived types to those in base types; overriding a method does not "move" where that method belongs in this hierarchy.
At the very beginning of this section, we noted that C# was designed with versioning in mind. This is one of those features that helps prevent "brittle base-class syndrome" from causing versioning problems.
The full quote makes it clear that Eric Lippert is talking specifically about method overloading, not just about how virtual methods work.
As an example, consider the following program:
class Base
{
public virtual void M2(int i) { }
}
class Derived : Base
{
public void M1(int i) { Console.WriteLine("Derived.M1(int)"); }
public void M1(float f) { Console.WriteLine("Derived.M1(float)"); }
public override void M2(int i) { Console.WriteLine("Derived.M2(int)"); }
public void M2(float f) { Console.WriteLine("Derived.M2(float)"); }
public static void Main()
{
Derived d = new Derived();
d.M1(1);
d.M2(1);
}
}
I think many developers would be surprised that the output is
Derived.M1(int)
Derived.M2(float)
Why would d.M2(1) invoke Derived.M2(float) even though Derived.M2(int) is a better match?
When the compiler is determining what the M1 in d.M1(1) refers to, the compiler sees that both M1(int) and M1(float) are introduced in Derived, so both overloads are applicable candidates. The compiler selects M1(int) over M1(float) as the best match for the integer argument 1.
When the compiler is determining what the M2 in d.M2(1) refers to, the compiler sees that M2(float) is introduced in Derived and is an applicable candidate. According to the overload resolution rules, "methods in a base class are not candidates if any method in a derived class is applicable". Because M2(float) is applicable, this rule prevents M2(int) from being a candidate. Even though M2(int) is a better match for the integer argument and even though it's overridden in Derived, it's still considered to be a method of Base.
Understanding that an overridden virtual method belongs to the class which introduces it, rather than the class that overrides it, makes it easier to understand the way class members are bound. Except when using dynamic objects, all bindings in C# are resolved at compile time. If a BaseClass declares a virtual method foo, and DerivedClass:BaseClass overrides foo, code which attempts to call foo on a variable of type BaseClass will always be bound to virtual method "slot" BaseClass.foo, which will in turn point to the actual DerivedClass.foo method.
This understanding can be especially important when dealing with generics, since in C#, unlike C++, members of generic types are bound according to the generics' constraints, rather than according to the concrete generic types. For example, suppose there were a SubDerivedClass:DerivedClass which created a new virtual method foo(), and one defined a method DoFoo<T>(T param) where T:BaseClass {param.foo();}. The param.foo() call would be bound to BaseClass.foo even if the method were invoked as DoFoo<SubDrivedClass>(subDerivedInstance). If the parameter were cast to SubDerivedClass before invoking foo, the call would be bound to SubDrivedClass.foo(), but the compiler can't tell when producing DoFoo<T> that T will be anything more specific than BaseClass, it can't bind to anything that doesn't exist in BaseClass.
Incidentally, there are times it would be useful if a class could simultaneously override a base-class member and create a new one; for example, given an abstract base class ReadableFoo with some abstract read-only property, it would be helpful if a class MutableFoo could both provide an override for that property and define a read-write property with the same name. Unfortunately, .net does not allow that. Given such a restriction, the best approach may be for ReadableFoo to provide a concrete non-virtual read-only property which calls an protected abstract method with a different name to get the value. That way, a derived class could shadow the read-only property with a read-write one (that would call the same virtual method for reading, or a new (possibly virtual) method for writing.
(following is untested)
class BaseClass
{
public virtual void foo() {Console.WriteLine("BaseClass.Foo");
}
class DerivedClass:BaseClass
{
public override void foo() {Console.WriteLine("Derived.Foo");
}
class SubDerivedClass:DerivedClass
{
public new virtual void foo() {Console.WriteLine("SubDerived.Foo");
}
class MegaDerivedClass:SubDerivedClass
{
public override void foo() {Console.WriteLine("MegaDerived.Foo");
}
void DoFoo1<T>(T param) where T:BaseClass
{
param.foo();
}
void DoFoo1<T>(T param) where T:SubDerivedClass
{
param.foo();
}
void test(void)
{
var megaDerivedInstance = new MegaDerivedClass();
DoFoo1<MegaDerivedClass>(megaDerivedInstance);
DoFoo2<MegaDerivedClass>(megaDerivedInstance);
}
A SubDerivedClass has two virtual foo() methods: BaseClass.foo() and SubDerivedClass.foo(). A MegaDerivedClass has those same two methods. Note that classes derived from SubDerivedClass() which attempt to override foo will override SubDerivedClass.foo() and will not affect BaseClass.foo(); with the declarations as above, no derivative of SubDerivedClass can override BaseClass.Foo. Note also that casting an instance of SubDerivedClass or a subclass thereof to DerivedClass or BaseClass will expose the BaseClass.foo virtual method for calling.
Incidentally, if the method declaration in SubDerivedClass had been friend new virtual void foo() {Console.WriteLine("SubDerived.Foo");, it would be impossible for other classes within the same assembly to override BaseClass.foo() (since any attempt to override foo() would override SubDerivedClass.foo()), but classes outside the assembly which derive from SubDerivedClass wouldn't see SubDerivedClass.foo() and could thus override BaseClass.foo().
What are differences between declaring a method in a base type "virtual" and then overriding it in a child type using the "override" keyword as opposed to simply using the "new" keyword when declaring the matching method in the child type?
I always find things like this more easily understood with pictures:
Again, taking joseph daigle's code,
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
If you then call the code like this:
Foo a = new Bar();
a.DoSomething();
NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)
Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.
The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
This prints false, if you used override it would have printed true.
(Base code taken from Joseph Daigle)
So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.
Here's some code to understand the difference in the behavior of virtual and non-virtual methods:
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
The new keyword actually creates a completely new member that only exists on that specific type.
For instance
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.
Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.
virtual / override tells the compiler that the two methods are related and that in some circumstances when you would think you are calling the first (virtual) method it's actually correct to call the second (overridden) method instead. This is the foundation of polymorphism.
(new SubClass() as BaseClass).VirtualFoo()
Will call the SubClass's overriden VirtualFoo() method.
new tells the compiler that you are adding a method to a derived class with the same name as a method in the base class, but they have no relationship to each other.
(new SubClass() as BaseClass).NewBar()
Will call the BaseClass's NewBar() method, whereas:
(new SubClass()).NewBar()
Will call the SubClass's NewBar() method.
The difference between the override keyword and new keyword is that the former does method overriding and the later does method hiding.
Check out the folllowing links for more information...
MSDN and Other
new keyword is for Hiding. - means you are hiding your method at runtime. Output will be based base class method.
override for overriding. - means you are invoking your derived class method with the reference of base class. Output will be based on derived class method.
My version of explanation comes from using properties to help understand the differences.
override is simple enough, right ? The underlying type overrides the parent's.
new is perhaps the misleading (for me it was). With properties it's easier to understand:
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
Using a debugger you can notice that Foo foo has 2 GetSomething properties, as it actually has 2 versions of the property, Foo's and Bar's, and to know which one to use, c# "picks" the property for the current type.
If you wanted to use the Bar's version, you would have used override or use Foo foo instead.
Bar bar has only 1, as it wants completely new behavior for GetSomething.
Not marking a method with anything means: Bind this method using the object's compile type, not runtime type (static binding).
Marking a method with virtual means: Bind this method using the object's runtime type, not compile time type (dynamic binding).
Marking a base class virtual method with override in derived class means: This is the method to be bound using the object's runtime type (dynamic binding).
Marking a base class virtual method with new in derived class means: This is a new method, that has no relation to the one with the same name in the base class and it should be bound using object's compile time type (static binding).
Not marking a base class virtual method in the derived class means: This method is marked as new (static binding).
Marking a method abstract means: This method is virtual, but I will not declare a body for it and its class is also abstract (dynamic binding).
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}