tags:

views:

362

answers:

7

Wondering what the difference is between the following:

Case 1 : Base Class

public void DoIt();

Case 1 : Inherited class

public new void DoIt();

Case 2 : Base Class

public virtual void DoIt();

Case 2 : Inherited class

public override void DoIt();

Both case 1 and 2 appear to have the same effect based on the tests I have ran. Is there a difference, is there a preferred way?

Thanks

Shiraz

+4  A: 

try following: (case1)

((BaseClass)(new InheritedClass())).DoIt()

Edit: virtual+override are resolved at runtime (so override really overrides virtual methods), while new just create new method with the same name, and hides the old, it is resolved at compile time -> your compiler will call the method it 'sees'

Yossarian
+6  A: 

In the first case you are hiding the definition in the parent class. This means that it will only be invoked when you are dealing with the object as the child class. If you cast the class to its parent type, the parent's method will be invoked. In the second instance, the method is overridden and will be invoked regardless of whether the object is cast as the child or parent class.

tvanfosson
+6  A: 

The new modifier instructs the compiler to use your child class implementation instead of the parent class implementation. Any code that is not referencing your class but the parent class will use the parent class implementation.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();

will call Derived.DoIt if that overrides Base.DoIt.

The override modifier may be used on virtual methods and must be used on abstract methods. This indicates for the compiler to use the last defined implementation of a method. Even if the method is called on a reference to the base class it will use the implementation overriding it.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}


Base b = new Derived();
Derived d = new Derived();
b.DoIt();
d.DoIt();

Will first call Base.DoIt, then Derived.DoIt. They're effectively two entirely separate methods which happen to have the same name, rather than the derived method overriding the base method.

rahul
+1  A: 

See here for an overview of what the new keyword does and its relation to the override keyword.

Rune Grimstad
+3  A: 

virtual: indicates that a function may be overriden by an inheritor

override: overrides the functionality of a virtual function in a base class, providing different functionality.

new: hides the original function (which doesn't have to be virtual), providing different functionality. This should only be used where it is absolutely necessary.

When you hide a method, you can still access the original method by down casting to the base class. This is useful in some scenarios, but dangerous.

Jon B
+1  A: 

Hi Shiraz,

The difference between the two cases is that in case 1, the base DoIt method does not get overridden, just hidden. What this means is that depending on the type of the variable depends on which method will get called. For example

BaseClass instance1 = new SubClass(); instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass(); instance2.DoIt(); // Calls sub class DoIt method

This can be really confusing and results in non expected behaviour and should be avoided if possible. So the preferred way would be case 2.

Shannon Cornish
+1  A: 

In case 1 if you used call the DoIt() method of the inherited class while the type is declared as the base class you will see the action of the base class even.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}
Matthew Whited