Shadowing in c# - base method gets called instead of derived

892 views Asked by At

I'm trying to figure out the concept of shadowing in c#. This is my code, which isn't behaving as I expect it to:

public class Animal
{
    public virtual void Foo()
    {
        Console.WriteLine("Foo Animal");
    }
}

public class Dog : Animal
{
    public new void Foo()
    {
        Console.WriteLine("Foo Dog");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dog dog1 = new Dog();
        ((Animal)dog1).Foo();
        Animal dog2 = new Dog();
        dog2.Foo();
    }
}

When the code in Main is executed, Foo() from the base class (Animal) is called, and from what I read about shadowing, Foo() from Dog should be called. Can someone explain what am i missing?

My example is according to this: https://msdn.microsoft.com/en-us/library/ms173153.aspx

UPDATE: This is the example from msdn:

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");
    }
}

When bcdc.Method1() is executed, Method1() from the derived class gets called, which isn't the case in my example.

3

There are 3 answers

0
Noctis On

In your case, dog1 which is a Dog will usually get you "Foo Dog", but because you explicitly tell it to be an Animal, it displays the "Foo Animal". Makes sense.

Then, with the dog2, which is an Animal, you expect the "Foo animal" to fire, because you said "hey, you're an animal", and even though you have virtual on Animal (which suggests that deriving classes should override this method, and then the resolution of what to call will happen on run time depending on the type), you use the new which hides it.


Still perfectly Ok. In their example, bcdc is of type BaseClass, but at runtime , since it's a Derived one, AND Method1 is using virtual AND override, on the base and derived, it gets called.

Because it's method2 isn't overriding the virtual, it calls the only one it knows about, the Base one. If instead of defining it as BaseClass, it would have been a DerivedClass, it would have found it's method2

2
arpitbakshi On

In your example when you do ((Animal)dog1).Foo() or dog2.Foo(), Foo method of Animal gets executed because when you run the application CLR first search the implementation in base(because of the reference to Animal) and then checks if it overridden in derived type or not, as You have not overridden the base class implementation it is calling the base method(Animal's Foo) instead of derived(Dog's Foo) in both the case.

UPDATE :

There is very small difference between override and new keyword. When you do override, does not matter which reference you are using it always calls overridden method when the object is of Derived type. In case of new keyword you are not doing overriding, you are actually hiding the base class implementation I meant here is you are hiding the implementation of base class for Derived type not for the base, so when you use reference of base for derived object like
Base obj = new Derived(); it always calls base method because it can not find the overridden method in derived.

0
Kira On

In the line, ((Animal)dog1).Foo(), first the object dog1 will be converted to type Animal from Dog. So it calls the method in base class Animal.

If you use override instead of the new keyword in the Foo method of dog class, you will get your expected result (i.e, Foo method of Dog class will be called).

In your code Animal dog2 = new Dog();, dog2 will be created as an object of Animal instead of Dog. So, calling the Foo method will invoke the method in Animal class.

You can call the Foo method in Dog class by using the following code ((Dog)dog2).Foo();. Here conversion from Animal to Dog class is possible because the variable dog2 is originally created from the constructor of Dog class