Click here to Skip to main content
15,881,882 members
Articles / Programming Languages / C#
Article

Function Overloading

Rate me:
Please Sign up or sign in to vote.
1.69/5 (16 votes)
10 Mar 20078 min read 117.7K   19   11
An exploration of function overloading in C#

Introduction

C# allows us to define multiple functions with the same name differing in the number type and order of arguments. This is termed as function overloading. This way, one does not have to remember the names of multiple functions that serve a similar core purpose. However, this can lead to problems. Let's explore.

The Problem

Let's write a simple C# program that implements a class named projector and contains an entry point function Main()

C#
class Projector
{
  public static void Main ()
  {
  }
}

Now let's make the projector functional by making it capable of displaying a string. To do so we add a function called DisplayString() as shown below.

C#
class Projector
{
  public static void DisplayString (string str)
  {
    System.Console.WriteLine (str);
  } 
  public static void Main ()
  {
    DisplayString ("Hello");
  }
}

Output

Hello

The above program compiles and runs successfully to display the string "Hello". Now let's enhance the projector by making it capable of displaying an integer in addition to displaying a string. To do so we add a function called DisplayInteger() as shown below.

C#
class Projector
{
  public static void DisplayString( string str )
  {
    System.Console.WriteLine( str );
  } 
  public static void DisplayInteger( int number )
  {
    System.Console.WriteLine( number);
  } 
  public static void Main()
  {
    DisplayString( "Hello" );
    DisplayInteger( 1234 );
  }
}

Output

Hello
1234

The above program compiles and runs successfully to display the string "Hello" and the integer "1234". Let's further enhance the projector to display a character. To do so we add a function called DisplayCharacter () as shown below.

C#
class Projector
{
  public static void DisplayString( string str )
  {
    System.Console.WriteLine( str );
  } 
  public static void DisplayInteger( int number )
  {
    System.Console.WriteLine( number);
  } 
  public static void DisplayCharacter( char c )
  {
    System.Console.WriteLine( c );
  } 
  public static void Main()
  {
    DisplayString( "Hello" );
    DisplayInteger( 1234 );
    DisplayCharacter( 'A' );
  }
}

Output

Hello
1234
A

The above program compiles and runs successfully to display the string "Hello", the integer "1234" and the character "A". We would refrain from making any further enhancements for the sake of simplicity but would like to make a point that if at all we decide to make further enhancements, the projector would be equipped with many Display functions like DisplayBoolean(), DisplayShort(), DisplayLong(), DisplayThis() and DisplayThat() etc. But then it would be inconvenient for us to remember the names of so many Display functions. Problem!

The Solution

Because C# has function overloading, one does not have to remember the names of multiple functions that serve a similar core purpose.

The projector in our example has three functions viz. DisplayString(), Display Integer() and DisplayCharacter(). Their core purpose is to display whatever is passed to them. We can apply function overloading here. We can have three functions named Display(). The first function will accept a string and display a string. The second function will accept an integer and display an integer. The last function will accept an character and display a character. Thus our enhanced Projector will now look like this.

C#
class Projector
{
  public static void Display( string str )
  {
    System.Console.WriteLine( str );
  } 
  public static void Display( int number )
  {
    System.Console.WriteLine( number);
  } 
  public static void Display( char c )
  {
    System.Console.WriteLine( c );
  } 
  public static void Main()
  {
    Display( "Hello" );
    Display( 1234 );
    Display( 'A' );
  }
}

Output

Hello
1234
A

The above program compiles and runs successfully to display the string "Hello", the integer "1234" and the character "A". As justified by the output, when the compiler encounters a function call Display("Hello") it invokes the function Display() that accepts string str as an argument. When the compiler encounters a function call Display(1234) it invokes the function Display() that accepts int number as an argument. When the compiler encounters a function call Display('A') it invokes the function Display() that accepts char c as an argument. Thus, you can say that the function Display() not only displays a string but also bears the load of displaying an integer as well as a character. Hence the name function overloading!

Functions with same name and different return types

Let us understand why there cannot be two or more functions with the same name and different return types within a single class.

Consider the following program

C#
class data
{
  string ch;
  char   ch;  
  public static void Main(){}
}

Output

P.cs(4,10): error CS0102: The class 'data' already contains a definition 
for 'ch'
P.cs(3,10): (Location of symbol related to previous error)

The above program fails to clear the compilation hurdle. At line 3 the compiler is told to treat ch as string. At line 4 the compiler is told to treat ch as char. The compiler gets confused! What should it treat ch as? String or a char? Hence the error!

Now lets enhance the program by making ch and empty function.

C#
class data
{
  string ch(){}
  char   ch(){}  
  public static void Main(){}
}

Output

P.cs(4,10): error CS0111: Class 'data' already defines a member called 'ch' 
with the same parameter types
P.cs(3,10): (Location of symbol related to previous error)

The above program fails to clear the compilation hurdle. At line 3 the compiler is told to treat ch as a string returning function that accepts no arguments and does nothing. At line 4 the compiler is told to treat ch as a char returning function that accepts no arguments and does nothing. The compiler gets confused! What should it treat ch as? A function that returns a string or a function that returns a char? Hence the error! Point proved. There cannot be two or more functions with the same name and different return types within a single class.

Function Signatures

We need to study the concept of function signatures to understand the working principle of function overloading.

Consider the following program

C#
class data
{
  string ch;
  string ch;  
  public static void Main(){}
}

Output

P.cs(4,10): error CS0102: The class 'data' already contains a definition 
for 'ch'
P.cs(3,10): (Location of symbol related to previous error)

The above program fails to clear the compilation hurdle. At line 3 the compiler is told to treat ch as a string. At line 4 the compiler is AGAIN told to treat ch as a string. The irritated compiler shouts "Enough! Don't give me the same instructions again and again!"

Now let's enhance the program by making ch an empty function.

C#
class data
{
  string ch(){}
  string ch(){}  
  public static void Main(){}
}

Output

P.cs(4,10): error CS0111: Class 'data' already defines a member called 'ch'
with the same parameter types
P.cs(3,10): (Location of symbol related to previous error)

The above program fails to clear the compilation hurdle. At line 3 the compiler is told to treat ch as a string-returning function that accepts no arguments and does nothing. At line 4 the compiler is AGAIN told to treat ch as a string-returning function that accepts no arguments and does nothing. The irritated compiler shouts "Enough! Don't give me the same instructions again and again!"

Now let's enhance the program by making a slight change at line 4. We make the second function display a string "Hello".

C#
class data
{
  string ch(){}
  string ch(){return "Hello";}  
  public static void Main(){}
}

Output

P.cs(4,10): error CS0111: Class 'data' already defines a member called 'ch'
with the same parameter types
P.cs(3,10): (Location of symbol related to previous error)

Error again! That too the same one we got in the earlier program. Observe the error carefully! It says that class data already defines a member called ch with the same parameter types. This means that the compiler is complaining about the parameter types of the function ch (). It is not at all complaining about the return type which is string in both the cases. In this case the compiler has nothing to do with what the function ch() can do. The first version of function ch() is empty. The successive version of ch() attempts to return a string "Hello". Despite this difference the compiler is just concerned about the name and type of parameters the function takes. In the above program the compiler understands that at line 3 it is told to treat ch as a string returning function that accepts no arguments. At line 4 the compiler is AGAIN told to treat ch as a string-returning function that accepts no arguments. This irritates the complier! The irritated compiler shouts "Enough! Don't give me the same instructions again and again!"

Well, I feel the compiler had had enough of irritation. Now let's enhance the program to make the compiler happy! We make a slight change at line 3. We make the first function ch() accept and return a string.

C#
class data
{
  string ch(string str){ return(str);}
  string ch(){return "Hello";}  
  public static void Main (){}
}

Bingo! The program compiles successfully! So what made the difference? How does the compiler differentiate functions? It differentiates functions by their names, number, type and order of the function arguments. In case the names of the functions are the same, the compiler differentiates them by number, type and order of the function arguments. In the above program we have two functions. Both have the same names i.e ch(). Since the names are the same, the compiler turns its attention to the number, type and order of the function arguments. The first function ch() accepts a string str as an argument. The second function ch() accepts absolutely nothing. Thus the two functions are totally different.

Thus, a function gets its identity from its name as well as number, type and order of its arguments. And this is the Function Signature. A function signature is composed of function name and number, type and order of its arguments.

To make things more clear lets consider a couple of examples and then move on. Consider the following program.

C#
class data
{
  void ch(string str){ System.Console.WriteLine(str);}
  void ch(int i){ System.Console.WriteLine(i);}  
  public static void Main (){}
}

The program compiles successfully! The compiler looks at the first function ch() as the function that accepts a string and the second function ch() as the function that accepts an integer. Hence it treats the two functions as two separate functions.

Consider the following program.

C#
class data
{
  void ch(string str , int i){ System.Console.WriteLine(str);}
  void ch(int i, string str){ System.Console.WriteLine(i);}  
  public static void Main (){}
}

The program compiles successfully! The compiler looks at the first function ch() as the function that accepts a string followed by an integer and the second function ch() as the function that accepts an integer followed by a string. Hence it treats the two functions as two separate functions.

Function Signatures and Access Specifiers and Access Modifiers

Let us study if access specifiers and access modifiers are a part of function signatures.

Consider the following program.

C#
class data
{
  void ch(){}
  void ch(){}  
  public static void Main (){}
}

Output

P.cs(4, 8): error CS0111: Class 'data' already defines a member called 'ch' 
with the same parameter types
P.cs(3, 8): (Location of symbol related to previous error)

The above program fails to pass the compilation hurdle because there are two functions of the same signature in the same scope. The name of the first function is ch() and it accepts no arguments. The name of the second function is ch() and it accepts no arguments.

Let us tamper with the above program by adding a public access specifier to the first ch() function.

C#
class data
{
  public void ch(){}
  void ch(){}  
  public static void Main (){}
}

Output

P.cs(4, 8): error CS0111: Class 'data' already defines a member called 'ch' 
with the same parameter types
P.cs(3, 15): (Location of symbol related to previous error)

Error! That too the same one we got in the earlier program. The name of the first function is ch() and it accepts no arguments. The name of the second function is ch() and it accepts no arguments. Adding a public access specifier to the first function ch() didn't make any difference. Thus Access specifiers are not a part of the function signature.

Let us tamper with the above program by making each function accept an integer as an argument.

class data
{
  public void ch(int i){}
  void ch(int i){}  
  public static void Main (){}
}

Output

P.cs(4, 8): error CS0111: Class 'data' already defines a member called 'ch' 
with the same parameter types
P.cs(3, 15): (Location of symbol related to previous error)

Error Again! That too the same one we got in the earlier program. The name of the first function is ch() and it accepts an integer argument. The name of the second function is ch() and it accepts an integer argument. And by now you very well know that two functions of the same signature are disallowed in the same scope.

Let us tamper with the above program by adding a ref access modifier to the integer argument of the first function ch() and out access modifier to the integer argument of the second ch() function.

C#
class data
{
  public void ch(ref int i){}
  void ch(out int i){}  
  public static void Main (){}
}

Output

P.cs(4,8): error CS0663: 'ch' cannot define overloaded methods which differ 
only on ref and out
P.cs(3,15): (Location of symbol related to previous error)

The above program fails to pass the compilation hurdle. The addition of access modifiers to the function arguments has made no difference at all when it comes to function signature. For the compiler, the above program contains two functions of the same signature. Hence the above program fails to compile.

The above examples make it pretty clear that access specifiers and access modifiers are NOT a part of function signatures.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
India India
I am a Software engineer with around 7+ years of experience. Most of my experience is in Storage technology.

Comments and Discussions

 
GeneralError in code Pin
Colin Angus Mackay9-Mar-07 6:02
Colin Angus Mackay9-Mar-07 6:02 
GeneralRe: Error in code Pin
Chetan Kudalkar10-Mar-07 2:29
Chetan Kudalkar10-Mar-07 2:29 
GeneralRe: Error in code Pin
Colin Angus Mackay10-Mar-07 3:21
Colin Angus Mackay10-Mar-07 3:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.