LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1812 min read

Method Overloading

Learn how C# lets you define multiple methods with the same name but different parameters.

What is Overloading?

Method overloading lets you define multiple methods with the same name within the same class, as long as their parameter lists differ in number, type, or order. This lets a method like `Add` work naturally with different types or numbers of arguments, without needing awkwardly distinct names like AddInts, AddDoubles, AddThreeNumbers.

static int Add(int a, int b) => a + b;
static double Add(double a, double b) => a + b;
static int Add(int a, int b, int c) => a + b + c;
Console.WriteLine(Add(2, 3)); // 5
Console.WriteLine(Add(2.5, 3.5)); // 6
Console.WriteLine(Add(1, 2, 3)); // 6
Fun Fact

You've already been using overloaded methods throughout this course without necessarily noticing — Console.WriteLine() itself has over a dozen overloads in the .NET standard library, accepting a string, an int, a double, a bool, an object, and more, all under the exact same method name.

Overloading Rules

  • Overloads must differ in the number, types, or order of parameters.
  • Return type alone is not enough to distinguish two overloads — two methods with the same name and parameters but different return types will not compile.
  • Parameter names don't matter for overload resolution — only their types and order.
  • Optional parameters and params can interact with overloading in ways that occasionally create ambiguity, covered below.
This does NOT compile — same parameters, different return type only
static int GetValue() { return 1; }
static double GetValue() { return 1.0; } // ❌ Error: differs only by return type

How the Compiler Chooses

At compile time (not runtime), C# looks at the exact argument types you pass and selects the single best-matching overload — this is called overload resolution. If no overload matches, or if two overloads match equally well and neither is more specific, you get a compile error rather than unpredictable runtime behavior.

static void Print(int value) => Console.WriteLine($"int: {value}");
static void Print(double value) => Console.WriteLine($"double: {value}");
Print(5); // int: 5 — exact match wins
Print(5.0); // double: 5 — exact match wins
Print(5L); // double: 5 — long has no exact overload, widens to double (the closer implicit conversion)

A Real-World Example

A logging utility is a classic, practical case for overloading — accepting a plain message, a message with a severity level, or a message with an associated exception, all under one intuitive Log name.

static void Log(string message)
{
Console.WriteLine($"[INFO] {message}");
}
static void Log(string message, string level)
{
Console.WriteLine($"[{level}] {message}");
}
static void Log(string message, Exception ex)
{
Console.WriteLine($"[ERROR] {message}: {ex.Message}");
}
Log("Server started");
Log("Disk space low", "WARNING");
Log("Failed to connect", new Exception("Timeout"));

Common Beginner Mistakes

Trying to overload by return type alone

The compiler needs to distinguish overloads purely from the arguments at the call site — it never looks at what you plan to do with the return value, so return type alone can never disambiguate.

Creating ambiguous overloads with optional parameters

void Foo(int a, int b = 0) and void Foo(int a) can conflict — calling Foo(5) could match either, causing a compile error about ambiguity.

Assuming overloading is "polymorphism"

Overloading (same name, different parameters, resolved at compile time) is a different concept from polymorphism/overriding (same signature, different behavior in a subclass, resolved partly at runtime) — covered in the polymorphism lesson later in this course.

FAQs

No — overloading is about multiple methods with the same name but different parameters in the same class, resolved entirely at compile time; overriding (covered in the Polymorphism lesson) replaces a base class's method behavior in a derived class, resolved partly at runtime.

Yes — constructor overloading is extremely common and is covered in depth in the Constructors lesson, letting you create an object in several different ways.

No hard limit — the .NET standard library itself has methods with dozens of overloads (Console.WriteLine being a prime example), though for your own code, keeping the number manageable aids readability.

Key Takeaways

  • Overloading lets one method name handle different parameter combinations, chosen at compile time.
  • Overloads must differ by parameter type, count, or order — not just return type.
  • The compiler picks the best-matching overload based on the exact argument types at the call site.
  • Overloading is distinct from overriding/polymorphism, covered later in this course.

Summary

Overloading gives a single, intuitive method name the flexibility to handle several different parameter shapes, resolved safely and predictably at compile time. Next, you'll learn scope — where a variable is actually visible and accessible within your code.

Next Lesson →

Scope