Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# method overload with inheritance

I always thought C# resolves method calls dynamically during runtime by looking at the runtime type of the method call receiver (i.e. the object before the dot).

However the following code sample works differently. If I use GenericSpaceShip in the code it returns "Generic"; if I use SpaceShip it returns "Specific". Note that the runtime type in both cases is SpaceShip.

So my question is: How does C# resolve the Visit method call and why does it look at the compile time rather than the runtime type in this situation?

Note that the two Visit methods have different parameters. As Patko points out, this means I cannot use virtual/override here.

class GenericSpaceShip
{
    public void Visit(GenericPlanet planet)
    {
        Console.WriteLine("Generic");
    }
}

class SpaceShip : GenericSpaceShip
{
    public void Visit(Planet planet)
    {
        Console.WriteLine("Specific");
    }
}

class GenericPlanet { }

class Planet : GenericPlanet { }

class Starter
{
    static void Main(string[] args)
    {
        // SpaceShip ship = new SpaceShip();
        GenericSpaceShip ship = new SpaceShip();
        Planet planet = new Planet();

        ship.Visit(planet); // => Generic
    }
}
like image 562
jonas Avatar asked Jun 19 '26 04:06

jonas


1 Answers

If you want to have really dynamic resolution, then you have to use dynamic keyword, like so:

static void Main(string[] args)
{
    dynamic ship = new SpaceShip();
    Planet planet = new Planet();

    ship.Visit(planet); // => Specific

    // also
    GenericPlanet genericPlanet = new GenericPlanet();
    ship.Visit(planet); // Generic
}

In this case behaviour will be something like you have described - type of the parameter matters. But what you most likely want is to have a method override, like so:

class GenericSpaceShip
{
    public virtual void Visit(GenericPlanet planet)
    {
        Console.WriteLine("Generic");
    }
}

class SpaceShip : GenericSpaceShip
{
    public override void Visit(GenericPlanet planet)
    {
        Console.WriteLine("Specific");
    }
}

In this case the Specific method will be called if you have an instance of SpaceShip and Generic method for instance of GenericSpaceShip, regardless of planet type. In this case type of the ship matters:

static void Main(string[] args)
{
    SpaceShip ship = new SpaceShip();
    Planet planet = new Planet();

    ship.Visit(planet); // => Specific

    // also
    GenericPlanet genericPlanet = new GenericPlanet();
    ship.Visit(planet); // Specific       
}

You would always get Generic if GenericSpaceShip was used instead.

like image 53
Patko Avatar answered Jun 21 '26 17:06

Patko