Search⌘ K
AI Features

Method Overloading

Explore how to use method overloading in C# to create methods with the same name but different parameter signatures. Understand how to differentiate methods by parameter count, types, order, and modifiers like ref or out. Learn to use the params keyword for variable arguments and improve your object-oriented programming skills by applying these concepts in class methods.

We often require methods that execute similar logic but accept different parameter types or quantities. Consider a Multiply() method designed for two operands. If the requirements expand to support three operands, we use overloading to maintain a consistent API.

Method signature

In C#, we can create several methods that have the same name but differ in other portions of their signature. A method signature consists of several parts:

  • Method name

  • Parameter quantities

  • Parameter types

  • Parameter order

  • Parameter modifiers

Note: Parameter names and the method return type are not part of the method signature.

Method overloading in C# creates several methods that have the same name but differ in any other parts of the signature.

C# 14.0
namespace MethodOverloading;
public class MathOperation
{
public double Multiply(int firstNumber, int secondNumber)
{
return firstNumber * secondNumber;
}
public double Multiply(int firstNumber, int secondNumber, int thirdNumber)
{
return firstNumber * secondNumber * thirdNumber;
}
}
  • Lines 5–8: Define a version of Multiply that accepts two integer parameters.

  • Lines 10–12: Define a version of Multiply that accepts three integer parameters, creating an overload.

The methods above have the same name but different signatures. This example distinguishes the overloads by parameter count. We can visualize the method signatures as follows:

Multiply(int, int);
Multiply(int, int, int);

Depending on the parameters we provide, the corresponding version of the method is called.

C# 14.0
using MethodOverloading;
MathOperation math = new MathOperation();
Console.WriteLine($"2 x 8 = {math.Multiply(2, 8)}");
Console.WriteLine($"6 x 12 x 7 = {math.Multiply(6, 12, 7)}");
  • Line 3: Instantiates the MathOperation class to access its members.

  • Line 4: Calls the two-parameter overload of Multiply.

  • Line 5: Calls the three-parameter overload of Multiply.

Pass an arbitrary number of parameters

We can extend our MathOperation class with another overload of the Multiply() method using the params keyword to handle any number of arguments:

C# 14.0
namespace MethodOverloading;
public class MathOperation
{
public double Multiply(params double[] numbersToMultiply)
{
if (numbersToMultiply.Length == 0)
{
return 0;
}
var result = numbersToMultiply[0];
for (int i = 1; i < numbersToMultiply.Length; i++)
{
result *= numbersToMultiply[i];
}
return result;
}
}
  • Line 5: Uses params to treat multiple comma-separated arguments as a single array.

  • Lines 7–10: Returns 0 if no arguments are passed to the method.

  • Lines 14–17: Multiplies every element in the array to produce the final result.

Parameter modifiers

Overloaded methods can differ based on modifiers like ref, in, or out. These modifiers change whether a method receives a copy of a value or a direct reference to the original variable’s memory address.

C# 14.0
namespace MethodOverloading;
public class Utility
{
// This method receives a copy of the integer (pass-by-value)
public static void IncreaseByOne(int number)
{
number++;
}
// This method receives a reference to the original variable (pass-by-reference)
public static void IncreaseByOne(ref int number)
{
number++;
}
}
  • Line 1: Uses a file-scoped namespace to organize the Utility class.

  • Lines 6–9: Defines a version of the method that works on a local copy of the input.

  • Lines 12–15: Defines an overload using the ref modifier to modify the caller's variable directly.

With the overloads defined in the Utility class, we invoke them from the entry point to observe the runtime behavior.

C# 14.0
using MethodOverloading;
var firstNumber = 8;
var secondNumber = 71;
Utility.IncreaseByOne(firstNumber);
Utility.IncreaseByOne(ref secondNumber);
Console.WriteLine(firstNumber); // Output: 8
Console.WriteLine(secondNumber); // Output: 72
  • Line 6: The first call to IncreaseByOne() invokes the pass-by-value implementation.

  • Line 7: The second call explicitly uses the ref keyword, so the compiler routes it to the pass-by-reference implementation.

  • Lines 9–10: Displays the final values to the console.

We cannot define overloads that differ only by ref, in, or out modifiers. The compiler views these as identical signatures at the metadata level, so attempting to use both ref int and out int for the same method name will cause a build error.

static void IncreaseByOne(ref int number)
{
}
// Not allowed
static void IncreaseByOne(out int number)
{
}

Furthermore, overloading in C# requires methods to be members of a class or struct. Local functions do not support this feature.