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
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With