404 Not Found

404 Not Found


nginx

Method Advanced

Method Overloading

Method overloading allows defining multiple methods with the same name in the same class, as long as their parameter lists differ. A different parameter list means a different number, type, or order of parameters. The return type does not participate in overload resolution.

Example

CSHARP
using System;

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

    public double Add(double a, double b)
    {
        return a + b;
    }

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

class Program
{
    static void Main()
    {
        Calculator calc = new Calculator();
        Console.WriteLine(calc.Add(1, 2));
        Console.WriteLine(calc.Add(1.5, 2.5));
        Console.WriteLine(calc.Add(1, 2, 3));
    }
}
▶ Try it Yourself
TEXT
3
4
6
💡 Tip: A different return type alone does not constitute an overload — the compiler will report an error.

Optional and Named Parameters

Optional parameters assign default values to parameters in the method declaration; these parameters can be omitted when calling the method. Named parameters pass values by specifying parameter names, without having to follow positional order.

Example

CSHARP
using System;

class Program
{
    static void Print(string msg, int count = 1, string prefix = "")
    {
        for (int i = 0; i < count; i++)
        {
            Console.WriteLine($"{prefix}{msg}");
        }
    }

    static void Main()
    {
        Print("Hello");
        Print("Hi", 3);
        Print(msg: "World", prefix: "> ");
        Print(prefix: ">> ", count: 2, msg: "Test");
    }
}
▶ Try it Yourself
TEXT
Hello
Hi
Hi
Hi
> World
>> Test
>> Test
⚠️ Note: Optional parameters must be placed after all required parameters.

The ref Parameter Modifier

The ref keyword passes a parameter by reference — modifications to the parameter inside the method affect the caller's variable. The variable must be initialized before the call, and the ref keyword must also be used at the call site.

Example

CSHARP
using System;

class Program
{
    static void Swap(ref int a, ref int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }

    static void Main()
    {
        int x = 10;
        int y = 20;
        Console.WriteLine($"Before: x={x}, y={y}");
        Swap(ref x, ref y);
        Console.WriteLine($"After: x={x}, y={y}");
    }
}
▶ Try it Yourself
TEXT
Before: x=10, y=20
After: x=20, y=10

The out Parameter Modifier

The out keyword also passes by reference, but the method must assign a value to the out parameter, and the variable does not need to be initialized before the call. It is commonly used when a method needs to return multiple values.

Example

CSHARP
using System;

class Program
{
    static bool TryParseInt(string s, out int result)
    {
        result = 0;
        foreach (char c in s)
        {
            if (c < '0' || c > '9')
                return false;
            result = result * 10 + (c - '0');
        }
        return true;
    }

    static void Main()
    {
        if (TryParseInt("123", out int number))
        {
            Console.WriteLine($"Parsed: {number}");
        }

        if (!TryParseInt("abc", out int fail))
        {
            Console.WriteLine("Parse failed");
        }
    }
}
▶ Try it Yourself
TEXT
Parsed: 123
Parse failed
📌 Key point: out parameters must be assigned before the method returns. Starting with C# 7, you can declare variables directly at the call site.

The in Parameter Modifier

The in keyword passes a parameter by reference as read-only — the method cannot modify the value of an in parameter. It is useful for passing large structs to avoid copy overhead while preventing accidental modification.

Example

CSHARP
using System;

struct BigData
{
    public long A, B, C, D, E, F, G, H;
}

class Program
{
    static void Process(in BigData data)
    {
        Console.WriteLine($"A={data.A}, B={data.B}");
    }

    static void Main()
    {
        BigData d = new BigData { A = 100, B = 200 };
        Process(in d);
        Process(d);
    }
}
▶ Try it Yourself
TEXT
A=100, B=200
A=100, B=200

ℹ️ Note: The in keyword can be omitted at the call site; the compiler will automatically pass by reference.

params Variable Arguments

The params keyword allows a method to accept a variable number of arguments — the compiler collects them into an array. A method can only have one params parameter, and it must be the last in the parameter list.

Example

CSHARP
using System;

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

    static void Main()
    {
        Console.WriteLine(Sum(1, 2, 3));
        Console.WriteLine(Sum(10, 20, 30, 40, 50));
        Console.WriteLine(Sum());
    }
}
▶ Try it Yourself
TEXT
6
150
0
⚠️ Note: params can only be used with single-dimensional arrays, and a method can have at most one params parameter.

Recursion Principles and Classic Examples

Recursion is a programming technique where a method calls itself. Every recursion must have a termination condition (base case); otherwise, it will cause a stack overflow.

Factorial

CSHARP
using System;

class Program
{
    static long Factorial(int n)
    {
        if (n <= 1)
            return 1;
        return n * Factorial(n - 1);
    }

    static void Main()
    {
        for (int i = 1; i <= 10; i++)
        {
            Console.WriteLine($"{i}! = {Factorial(i)}");
        }
    }
}
TEXT
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800

Fibonacci Sequence

CSHARP
using System;

class Program
{
    static int Fibonacci(int n)
    {
        if (n <= 0) return 0;
        if (n == 1) return 1;
        return Fibonacci(n - 1) + Fibonacci(n - 2);
    }

    static void Main()
    {
        for (int i = 0; i <= 10; i++)
        {
            Console.Write($"{Fibonacci(i)} ");
        }
        Console.WriteLine();
    }
}
TEXT
0 1 1 2 3 5 8 13 21 34 55
🔥 Performance warning: Naive recursion for the Fibonacci sequence involves a lot of redundant computation, with time complexity O(2^n). In production, use iteration or memoization to optimize.

Local Functions

C# 7 introduced local functions, allowing methods to be defined inside other methods. Local functions can only be accessed within their containing method and are useful for extracting helper logic used only in a specific method.

Example

CSHARP
using System;

class Program
{
    static int[] GetEvenSquares(int[] numbers)
    {
        bool IsEven(int n) => n % 2 == 0;
        int Square(int n) => n * n;

        System.Collections.Generic.List<int> result = new System.Collections.Generic.List<int>();
        foreach (int n in numbers)
        {
            if (IsEven(n))
            {
                result.Add(Square(n));
            }
        }
        return result.ToArray();
    }

    static void Main()
    {
        int[] data = { 1, 2, 3, 4, 5, 6, 7, 8 };
        int[] result = GetEvenSquares(data);
        Console.WriteLine(string.Join(", ", result));
    }
}
▶ Try it Yourself
TEXT
4, 16, 36, 64
💡 Tip: Local functions can capture local variables from the containing method and have lower overhead than lambda expressions.

Variable Scope

A variable's scope determines where it can be accessed. In C#, there are three main scope levels: block scope (inside if/for/while blocks), method scope (local variables defined within a method), and class scope (fields defined in a class).

Example

CSHARP
using System;

class ScopeDemo
{
    int classField = 100;

    void MethodA()
    {
        int localVar = 10;
        Console.WriteLine($"classField={classField}, localVar={localVar}");

        if (true)
        {
            int blockVar = 20;
            Console.WriteLine($"blockVar={blockVar}");
        }
    }

    void MethodB()
    {
        Console.WriteLine($"classField={classField}");
    }
}

class Program
{
    static void Main()
    {
        ScopeDemo demo = new ScopeDemo();
        demo.MethodA();
        demo.MethodB();
    }
}
▶ Try it Yourself
TEXT
classField=100, localVar=10
blockVar=20
classField=100

Rule: You cannot declare local variables with the same name in the same method. Inner code blocks can access outer variables, but outer blocks cannot access inner block variables.

❓ FAQ

Q Can method overloading be based solely on return type?
A No, the compiler matches methods based on arguments at the call site; return type is not part of the signature. Q: What is the core difference between ref and out? A: ref requires initialization before the call; out requires assignment inside the method. ref passes an existing value that can be modified; out is typically used to return additional results. Q: Can params arguments be null? A: Yes, params is essentially an array; passing null does not automatically create an empty array, so null checking is needed inside the method. Q: Is recursion always slower than iteration? A: Not necessarily, but recursion has stack depth limits and call overhead; deep recursion can lead to StackOverflowException. Q: What is the difference between local functions and lambda expressions? A: Local functions are true methods with no delegate overhead, supporting generics and ref/out; lambdas generate delegates or expression trees with extra allocations.

📖 Summary

  • Method overloading: same name, different parameters; return type does not participate
  • Optional parameters: assign default values at declaration, must be placed after required parameters
  • Named parameters: pass values by parameter name, breaking positional constraints
  • ref: pass by reference, must initialize before calling
  • out: pass by reference, must assign inside the method, no initialization required before calling
  • in: read-only pass by reference, prevents modification and avoids copying
  • params: variable number of arguments, compiled as an array, only one allowed and must be last
  • Recursion: a method calls itself; must have a termination condition; watch for performance and stack overflow
  • Local functions: methods defined inside methods, a C# 7+ feature with lower overhead than lambdas
  • Variable scope: block < method < class; inner can access outer, outer cannot access inner

📝 Exercises

  1. Write three overloaded Multiply methods accepting two ints, two doubles, and three ints respectively, returning the product.
  2. Write a method void Log(string msg, string level = "INFO", bool timestamp = true) and call it at least three times using named parameters in different orders.
  3. Write a void Increment(ref int value) method that increments the passed integer by 1, and verify in Main that the variable is indeed modified.
  4. Write a bool TryDivide(int a, int b, out double result) method that returns false when b is 0, otherwise returns the division result via out.
  5. Write a double Average(params double[] values) method that calculates the average of all arguments, handling the empty array case.
  6. Implement a recursive method to calculate 1+2+3+...+n and compare the result with an iterative version.
  7. Write a method that uses a local function internally to determine whether a number is prime, and returns all prime numbers from 1 to 50.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏