0

I have been recently stumbled by the way the C# compiler resolves the method calls for methods hiding base classes methods. I have written the following tests to expose my problem:

[TestClass]
public class UnitTest1
{
    public class Car
    {
        public int GetNumberOfSeets()
        {
            return 4;
        }
    }

    public class BmwZ4 : Car
    {
        public new int GetNumberOfSeets()
        {
            return 2;
        }
    }

    [TestMethod]
    public void TestBmwNumberOfSeets1()
    {
        BmwZ4 bmw = new BmwZ4();
        Assert.AreEqual(2, bmw.GetNumberOfSeets());
    }

    [TestMethod]
    public void TestBmwNumberOfSeets2()
    {
        var bmw = new BmwZ4();
        Assert.AreEqual(2, bmw.GetNumberOfSeets());
    }

    [TestMethod]
    public void TestBmwNumberOfSeets3()
    {
        Car bmw = new BmwZ4();
        Assert.AreEqual(2, bmw.GetNumberOfSeets());
    }
}

Surprisingly TestBmwNumberOfSeets1 and TestBmwNumberOfSeets2 are working perfectly fine where as TestBmwNumberOfSeets3 is just not working.

Can somebody explain to me why using a Car as the receiving type (implicit upcast) will transform my brand new BMW into a simple Car?

EDIT: I understood that by using the hiding mechanism, the method that will be called depends on the type of the variable calling the method. There is no dynamic dispatch. But why? It would have been easy for the compiler to use the dynamic type instead of the statically declared one.

The hiding mechanism in my mind is to be used when one want to override a class which is not sealed and does not belong to him (using a third party API) and wants to create a custom behavior for a method that is not marked virtual. That is the main goal. But if you don't have dynamic dispatch, the feature is purely useless and very dangerous to use.

  • 2
    Because you are hiding the method, not overriding it. Since the method is not virtual, you don't get dynamic dispatch, so the method you get is the one defined on the type of the reference you've got: `Car`. – Blorgbeard Sep 14 '14 at 22:51
  • NEVER use the keyword new because the behavior you've demonstrated is what you get as a result. The method called changes depending on the type of the variable used to reference an instance of as subclass using applying the new modifier to a base class's method. It's extremely dangerous code especially in the hands of your average developer who doesn't understand the nuances of the C# language. – Mick Sep 15 '14 at 00:25
  • I know it is a bad habit to use the hiding mechanism over inheritance. But I was using it because I was dealing with a code that does not belong to me which is precisely the kind of use cases for this feature of the language. But I do agree I will NEVER use it again. It is a broken feature! – Biarnès Adrien Sep 16 '14 at 07:23

1 Answers1

0

If you do

public class Car
{
    public virtual int GetNumberOfSeets()
    {
        return 4;
    }
}

Then

public class BmwZ4 : Car
{
    public override int GetNumberOfSeets()
    {
        return 2;
    }
}

Your tests will pass. As your code stands now your test tests the wrong thing. As you explicitly tells it to be a Car and not a BmwZ4.

This is called Subtype Polymorphism

AlexanderBrevig
  • 1,967
  • 12
  • 17
  • This is an incomplete explanation and ptentionally misleading – Mick Sep 15 '14 at 00:04
  • Feel free to edit the post and make it clearer. I'm trying to get across that his expectation of what new does - is in fact what virtual/override is for. – AlexanderBrevig Sep 15 '14 at 00:08
  • A demonstration of how the keyword new behaves would be required for a complete answer – Mick Sep 15 '14 at 00:18
  • To be fair he already did demonstrate that, with a test even. But I agree, guess I'm just too lazy now that it's marked as a dupe anyways. Thanks for your input. – AlexanderBrevig Sep 15 '14 at 00:20
  • 1
    I'd also mention on when to use the new keyword, which would be NEVER if you are able to edit the code for the base class and still probably never when you can't edit the base class. – Mick Sep 15 '14 at 00:22
  • I know what polymorphism is and how to override a method. That is not the point of the question. I was asking why the hiding mechanism of C# is working the way it does. Blorgbeard and Mick gave me a part of the answer telling me that you don't get dynamic dispatch (the method called changes depending on the type of the variable)... Ok but why? I mean the compiler must be able to determine the dynamic type and therefor call the right method? I just don't get it... – Biarnès Adrien Sep 16 '14 at 07:32
  • It /is/ calling the right method. It's calling `Car.GetNumberOfSeets`. The only way you can make it call `BmwZ4.GetNumberOfSeets` from a `Car` that is `BmwZ4` you need `virtual/override`. This is the intended behavior. – AlexanderBrevig Sep 16 '14 at 08:15