Method Overloading in C#: How Signatures Work
Method overloading in C# enables a class to define multiple methods with the exact same name, as long as each method possesses a distinct signature. At compile time, the C# compiler evaluates the arguments provided during a method call to determine and bind the execution to the most specific matching version. This guide covers the precise mechanics of method signatures, what variations the compiler accepts, and the common pitfalls that cause ambiguity or compilation errors.
What Constitutes a Method Signature?
In C#, a method signature consists exclusively of:
- The method name.
- The number (arity) of parameters.
- The data types of the parameters.
- The order of the parameter types.
- Parameter modifiers (specifically
ref,out, andin).
Elements such as the return type, parameter names, and access
modifiers (public, private, etc.) are
not part of the method signature.
Valid Signature Differences
To successfully overload a method, the parameter list must differ in at least one of the following ways:
1. Number of Parameters
The simplest way to overload is by varying the parameter count.
public class Calculator
{
public int Add(int a, int b) => a + b;
public int Add(int a, int b, int c) => a + b + c;
}2. Types of Parameters
Methods can accept the same number of arguments, provided their data types differ.
public class Printer
{
public void Print(string message) => Console.WriteLine(message);
public void Print(int number) => Console.WriteLine(number);
}3. Order of Parameter Types
If two methods share the same parameter types, varying the sequence creates distinct signatures.
public class Display
{
public void Render(string label, int count) { }
public void Render(int count, string label) { }
}4. Parameter
Modifiers (ref, out, in vs.
Value)
The compiler treats pass-by-reference modifiers as distinct from standard pass-by-value parameters.
public class Processor
{
public void Process(int data) { }
public void Process(ref int data) { } // Valid overload
}Invalid Signature Differences
Attempting to overload methods based solely on the following factors will cause a compile-time error:
Return Types: You cannot overload a method based exclusively on what it returns. The signature does not include the return type because a caller can execute a method without capturing its return value, leaving the compiler unable to determine which method to invoke.
// Compiler Error: CS0111 public int GetData() => 42; public string GetData() => "42";Parameter Names: Renaming parameters without changing their types does not alter the signature.
// Compiler Error: CS0111 public void Log(string message) { } public void Log(string text) { }refvs.out: While value vs. reference is a valid distinction, you cannot overload a method where the only difference between two signatures isrefversusout(orin). The runtime treats both internally as managed pointers.// Compiler Error: CS0663 public void Update(ref int value) { } public void Update(out int value) { value = 0; }
Compile-Time Resolution and Ambiguity
Method overloading is an implementation of compile-time (static) polymorphism. When a call occurs, the compiler uses overload resolution to pick the best candidate:
- Exact Match: The compiler searches for a method whose parameter types match the argument types exactly.
- Implicit Conversions: If an exact match is missing,
the compiler evaluates candidates that accept arguments via implicit
type conversion (e.g., passing an
intto a parameter typed asdouble). - Ambiguity Errors: If two or more methods are equally viable after implicit conversions—or when optional parameters overlap with existing signatures—the compiler throws a CS0121 error (the call is ambiguous). In these cases, explicit casting at the call site is required to specify the intended overload.