#684 – Hidden Base Class Members Aren’t Really Hidden

When authoring a derived class, you can hide a member of the base class using the new keyword.  For a method, this indicates that the method in your derived class replaces the method in the base class and will be called when invoked on objects of the derived type.  (It also means that the method will not behave polymorphically).

    public class Dog
    {
        public virtual void Bark()
        {
            Console.WriteLine("Dog: Woof");
        }
    }

    public class Terrier : Dog
    {
        public new void Bark()
        {
            Console.WriteLine("Terrier: Yip yip");
        }
    }

However, if you have an instance of the derived class and cast it to the type of its base class, you’ll end up accessing the method in the base class after all.

            Terrier t = new Terrier();

            t.Bark();         // Yip yip

            ((Dog)t).Bark();  // Woof

#683 – Two Ways an Object Can Behave Polymorphically

There are a couple of different ways that an object can behave polymorphically.  Here are two examples.

Polymorphic behavior #1 – access instance of subclass using reference to base class.

    public class Dog
    {
        public virtual void Bark()
        {
            Console.WriteLine("Dog: Woof");
        }
    }

    public class Terrier : Dog
    {
        public override void Bark()
        {
            Console.WriteLine("Terrier: Yip yip");
        }
    }
            // Terrier method called through Dog reference
            Dog d = new Terrier();
            d.Bark();

Polymorphic behavior #2 – Base class calls method that is overridden in derived class

        // Dog.GuardUs
        public void GuardUs()
        {
            Bark();
        }
            Terrier t = new Terrier();
            t.GuardUs();

#682 – The Real Reason for the new Keyword

Here’s a scenario that illustrates the main reason for the new keyword, allowing a method to not behave polymorphically.

Suppose you use a third-party library that defines a Dog class and you create a Terrier class in your own code that derives from Dog and defines a Speak method.  (Dog does not have a Speak method).

Now let’s say you get a new version of the Dog library in which they’ve added their own Speak method, which is virtual and which they call from the Dog constructor.

Now, when you construct a Terrier object, the Dog constructor will call Speak.  But by default, it’s Dog.Speak that’s called, rather than Terrier.Speak.  The compiler won’t just automatically make Speak behave polymorphically.

When you re-compile your code, you’ll get a warning indicating that you should make your intent explicit, by either marking Terrier.Speak as new (non-polymorphic) or as override (polymorphic).