Methods encapsulate reusable logic inside classes or structs. C# supports rich parameter syntax and method overloading.

Basic Methods

  class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Divide(double a, double b)
    {
        if (b == 0) throw new DivideByZeroException();
        return a / b;
    }
}

var calc = new Calculator();
Console.WriteLine(calc.Add(3, 4));       // 7
Console.WriteLine(calc.Divide(10, 2));   // 5
  

Optional and Named Parameters

  void Greet(string name, string greeting = "Hello", bool loud = false)
{
    string msg = $"{greeting}, {name}!";
    Console.WriteLine(loud ? msg.ToUpper() : msg);
}

Greet("Alice");
Greet("Bob", greeting: "Hi");
Greet("Charlie", loud: true);
  

Params Array

  int Sum(params int[] numbers)
{
    int total = 0;
    foreach (int n in numbers)
        total += n;
    return total;
}

Console.WriteLine(Sum(1, 2, 3, 4));  // 10
  

Method Overloading

  class Printer
{
    public void Print(int value) => Console.WriteLine($"Int: {value}");
    public void Print(string value) => Console.WriteLine($"String: {value}");
    public void Print(int value, string label) =>
        Console.WriteLine($"{label}: {value}");
}
  

The compiler selects the overload based on argument types and count.

Expression-Bodied Members

  class Circle
{
    public double Radius { get; set; }
    public double Area => Math.PI * Radius * Radius;
    public double Circumference() => 2 * Math.PI * Radius;
}
  

Local Functions

  int Factorial(int n)
{
    return LocalFact(n);

    int LocalFact(int x)
    {
        return x <= 1 ? 1 : x * LocalFact(x - 1);
    }
}

Console.WriteLine(Factorial(5));  // 120
  

Local functions keep helper logic scoped to the method that uses it.

ref and out Parameters

  bool TryParse(string input, out int result)
{
    return int.TryParse(input, out result);
}

void Swap(ref int a, ref int b)
{
    (a, b) = (b, a);
}

if (TryParse("42", out int value))
    Console.WriteLine(value);
  

out must be assigned before the method returns; ref requires an initialized variable.

Generic Methods

  T Max<T>(T a, T b) where T : IComparable<T>
{
    return a.CompareTo(b) > 0 ? a : b;
}

Console.WriteLine(Max(3, 7));
Console.WriteLine(Max("apple", "banana"));
  

Extension Methods

  public static class StringExtensions
{
    public static bool IsValidEmail(this string s) =>
        s.Contains('@') && s.Contains('.');
}

Console.WriteLine("[email protected]".IsValidEmail());
  

Define extension methods in static classes; they appear as instance methods on the extended type.

Deconstructing Returns

  (int quotient, int remainder) Divide(int a, int b) =>
    (a / b, a % b);

var (q, r) = Divide(17, 5);
Console.WriteLine($"17 / 5 = {q} remainder {r}");
  

Common Pitfalls

  • Too many optional parameters make call sites ambiguous — use overloads or builder pattern.
  • Extension methods cannot access private members of the extended type.
  • Recursive methods without a base case cause StackOverflowException.