Overloading Methods and Constructors

Often you’ll want to have more than one function with the same name. The most common example of this is to have more than one constructor. In the examples shown so far, the constructor has taken a single parameter: a DateTime object. It would be convenient to be able to set new Time objects to an arbitrary time by passing in year, month, date, hour, minute, and second values. It would be even more convenient if some clients could use one constructor, and other clients could use the other constructor. Function overloading provides for exactly these contingencies.

The signature of a method is defined by its name and its parameter list. Two methods differ in their signatures if they have different names or different parameter lists. Parameter lists can differ by having different numbers or types of parameters. For example, in the following code the first method differs from the second in the number of parameters, and the second differs from the third in the types of parameters:

void myMethod(int p1);
void myMethod(int p1, int p2);
void myMethod(int p1, string s1);

A class can have any number of methods, as long as each one’s signature differs from that of all the others.

Example 4-9 illustrates our Time class with two constructors, one which takes a DateTime object, and the other which takes six integers.

Example 4-9. Overloading the constructor

public class Time
{
   // public accessor methods
   public void DisplayCurrentTime( )
   {
      System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}", 
         Month, Date, Year, Hour, Minute, Second);
   }


   // constructors
   public Time(System.DateTime dt)
   {
      Year =      dt.Year;
      Month =     dt.Month;
      Date =      dt.Day;
      Hour =      dt.Hour;
      Minute =    dt.Minute;
      Second =    dt.Second;
   }

    public Time(int Year, int Month, int Date, 
         int Hour, int Minute, int Second)
      {
         this.Year =     Year;
         this.Month =    Month;
         this.Date =     Date;
         this.Hour =     Hour;
         this.Minute =   Minute;
         this.Second =   Second;
     }

   // private member variables
   private int Year;
   private int Month;
   private int Date;
   private int Hour;
   private int Minute;
   private int Second;

}

public class Tester
{
   static void Main( )
   {
      System.DateTime currentTime = System.DateTime.Now;

      Time t = new Time(currentTime);
      t.DisplayCurrentTime( );

      Time t2 = new Time(2005,11,18,11,03,30);
      t2.DisplayCurrentTime( );

   }

}

As you can see, the Time class in Example 4-9 has two constructors. If a function’s signature consisted only of the function name, the compiler would not know which constructors to call when constructing t1 and t2. However, because the signature includes the function argument types, the compiler is able to match the constructor call for t1 with the constructor whose signature requires a DateTime object. Likewise, the compiler is able to associate the t2 constructor call with the constructor method whose signature specifies six integer arguments.

When you overload a method, you must change the signature (i.e., the name, number, or type of the parameters). You are free, as well, to change the return type, but this is optional. Changing only the return type does not overload the method, and creating two methods with the same signature but differing return types will generate a compile error. This is illustrated in Example 4-10:

Example 4-10. Varying the return type on overloaded methods

public class Tester
{
   private int Triple(int val)
   {
      return 3 * val;
   }

   private long Triple (long val)
   {
      return 3 * val;
   }

   public void Test( )
   {
      int x = 5;        
      int y = Triple(x);
      System.Console.WriteLine("x: {0}  y: {1}", x, y);

      long lx = 10;
      long ly = Triple(lx);
      System.Console.WriteLine("lx: {0}  ly: {1}", lx, ly);
           
   }
   static void Main( )
   {
      Tester t = new Tester( );
      t.Test( );
   }
}

In this example, the Tester class overloads the Triple( ) method, one to take an integer, the other to take a long. The return type for the two Triple( ) methods varies. Although this is not required, it is very convenient in this case.

Get Programming C#, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.