This article discusses one of those programming topics that may be confusing at first but seems obvious once you know it.
As you know, C# enables you to overload the same method in a class with different arguments. But it’s also possible to overload a method with arguments that inherit from one another.
Consider this simple example of Base and Derived classes:
class Base { } class Derived : Base { }
Here we overload the Do method with a single object, Base and Derived argument. In this example, Derived inherits from Base which inherits from object:
class Methods { public void Do( object o ) { } public void Do( Base b ) { } public void Do( Derived d ) { } }
Question #1: Which overload executes?
Quick quiz: if you pass a Derived object to the Do method, which overload will execute? Answer: the overload with the most-derived arguments that match the object passed.
So in this example, if you pass a Derived object to the Do method, it will execute the Do( Derived d ) method. If you pass a Base object to the Do method, it will execute the Do( Base b ) method. And of course if you pass a different object altogether (such as DateTime) to the Do method, it will execute the Do( object o ) method.
Question #2: Does the overload selection occur at compile or run time?
The overload selected is based on the compile-time declaration of the argument being passed, not the run-time instance. This is because the compiler chooses which method overload to execute at compile-time, and hence it has to rely on the declaration of the passed object.
So in this example, if you pass an argument to the Do method that’s declared at compile-time as a Derived object, it will execute the Do( Derived d ) method as you would expect. But if you pass an argument that’s declared at compile-time as a Base object but currently references a Derived object, it will execute the Do( Base b ) method.
To be clear, if you declare a variable as a Base:
Base b2 = null;
It doesn’t matter if you later assign it to a Derived object:
b2 = new Derived();
It will still execute the Do( Base b ) overload, even though the variable references a Derived object.
Simple Console Program
Here is a simple console program that demonstrates this concept:
using System; namespace CSharp411 { class Program { static void Main( string[] args ) { object o1 = new object(); object o2 = new Base(); object o3 = new Derived(); Base b1 = new Base(); Base b2 = new Derived(); Derived d1 = new Derived(); DateTime t1 = new DateTime(); Methods methods = new Methods(); methods.Do( o1 ); methods.Do( o2 ); methods.Do( o3 ); methods.Do( b1 ); methods.Do( b2 ); methods.Do( d1 ); methods.Do( t1 ); Console.ReadLine(); } } class Methods { public void Do( object o ) { Write( "object", o ); } public void Do( Base b ) { Write( "Base", b ); } public void Do( Derived d ) { Write( "Derived", d ); } private void Write( string method, object obj ) { Console.WriteLine( "Do( {0} ) on {1}", method, obj.GetType().Name ); } } class Base { } class Derived : Base { } }
Program Output
Here is the console program output:
Do( object ) on Object
Do( object ) on Base
Do( object ) on Derived
Do( Base ) on Base
Do( Base ) on Derived
Do( Derived ) on Derived
Do( object ) on DateTime
Thak you for the news
There are 5 houses in five different colors
In each house lives a different nationality.
These 5 owners drink a certain beverage, smoke a certain brand of cigar and keep a certain pet.
No owners have the same pet, smoke the same brand of cigar, or drink the same beverage.
The CLUES:
The Brit lives in the Red house.
The Swede keeps dogs as pets.
The Dane Drinks tea.
The Green House is on the left of the White House.
The Green House’s owner drinks coffee.
The person who smokes Pall Mall rears birds.
The owner of the yellow house smokes Dunhill.
The man in the center house drinks milk.
The Norwegian lives in the first house.
The man who smokes Blends lives next to the one who keeps cats
The man who keeps horses lives next to the man who smokes Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Norwegian lives next to the Blue House.
The man who smokes Blends has a neighbor who drinks water.
The QUESTION:
Who owns the fish?
Hi,
In case 5 of your example:
Base b2 = new Derived();
leads to:
Do( Base ) on Derived
Is it possible to get b2 handled by
public void Do( Derived d )
rather than by
public void Do( Base d )
?
I have a situation where I have to access the Methods class through a helper method: eg:
using System;
using System.Collections.Generic;
using System.Text;
namespace TestCon
{
class Program
{
static void Main( string[] args )
{
object o1 = new object();
object o2 = new Base();
object o3 = new Derived();
Base b1 = new Base();
Base b2 = new Derived();
Derived d1 = new Derived();
DateTime t1 = new DateTime();
Methods methods = new Methods();
PreMethods prem = new PreMethods();
methods.Do( o1 );
methods.Do( o2 );
methods.Do( o3 );
methods.Do( b1 );
methods.Do( b2 );
prem.Do(d1); // <—
methods.Do( d1 );
methods.Do( t1 );
Console.ReadLine();
}
}
class PreMethods
{
Methods methods = new Methods();
public void Do(Base o)
{
methods.Do(o);
}
}
class Methods
{
public void Do( object o )
{
Write( "object", o );
}
public void Do( Base b )
{
Write( "Base", b );
}
public void Do( Derived d )
{
Write( "Derived", d );
}
private void Write( string method, object obj )
{
Console.WriteLine( "Do( {0} ) on {1}", method, obj.GetType().Name );
}
}
class Base { }
class Derived : Base { }
}