C# 方法

定义、参数修饰符、重载、可选参数、以及局部函数。

Beginner
Key Points`ref` 双向传值,`out` 只出不进,`in` 只进不出且避免复制。

定义与调用

C#
class Calc
{
    public int Add(int a, int b) => a + b;

    public static double Avg(params double[] nums)
    {
        if (nums.Length == 0) return 0;
        double sum = 0;
        foreach (var n in nums) sum += n;
        return sum / nums.Length;
    }
}

var c = new Calc();
Console.WriteLine(c.Add(1, 2));
Console.WriteLine(Calc.Avg(1, 2, 3, 4));
Output
3
2.5

参数修饰符

C#
// ref:双向
void Increment(ref int x) => x++;

// out:方法内必须赋值
bool TryHalf(int input, out int result)
{
    if (input % 2 != 0) { result = 0; return false; }
    result = input / 2;
    return true;
}

// in:只读引用,避免大结构体复制
double Length(in (double X, double Y) p) => Math.Sqrt(p.X * p.X + p.Y * p.Y);

int n = 10;
Increment(ref n);
Console.WriteLine(n);

if (TryHalf(8, out int half)) Console.WriteLine(half);
Console.WriteLine(Length((3, 4)));
Output
11
4
5
ModifierDirectionMust assignUse
(无)传入否默认,值复制
ref双向调用前需要改调用方变量
out只出方法内返回多个值
in只入否大结构体只读传参

可选参数与命名参数

C#
void Connect(string host, int port = 80, bool ssl = false, int timeout = 30)
{
    Console.WriteLine($"{host}:{port} ssl={ssl} timeout={timeout}");
}

Connect("example.com");
Connect("example.com", 443, true);
Connect("example.com", ssl: true);          // 命名参数跳过 port
Connect(timeout: 5, host: "a.com");
Output
example.com:80 ssl=False timeout=30
example.com:443 ssl=True timeout=30
example.com:80 ssl=True timeout=30
a.com:80 ssl=False timeout=5

Named arguments make call sites self-documenting: Connect("a.com", true) is opaque, Connect("a.com", ssl: true) is clear. Optional parameters must follow required ones.

重载

C#
class Printer
{
    public void Print(int x) => Console.WriteLine($"int {x}");
    public void Print(string s) => Console.WriteLine($"string {s}");
    public void Print(int x, int y) => Console.WriteLine($"two ints {x} {y}");
    public void Print(double d) => Console.WriteLine($"double {d}");
}

var p = new Printer();
p.Print(1);
p.Print("a");
p.Print(1, 2);
p.Print(1.5);
Output
int 1
string a
two ints 1 2
double 1.5

Overloads differ by parameter types and count, never by return type. p.Print(1) picks int — with both long and int overloads, int is the better match.

局部函数与表达式体

C#
int Fibonacci(int n)
{
    if (n < 2) return n;
    return Fib(n - 1) + Fib(n - 2);

    // 局部函数:只在 Fibonacci 内部可见
    int Fib(int x) => x < 2 ? x : Fib(x - 1) + Fib(x - 2);
}

Console.WriteLine(Fibonacci(10));

// 表达式体方法
static int Square(int x) => x * x;
Console.WriteLine(Square(7));
Output
55
49
Local functions suit recursion better than lambdas, which cannot reference themselves at declaration. They also support ref/out and can be static (no closure allocation).

Friends & Partners