目录

ref 和 out

在 C# 中,方法参数默认是 值传递refout 是两个关键字,可以改变这一行为,使方法能够 直接修改外部变量


二者核心区别

关键字 调用前必须初始化? 方法内部必须赋值? 用途
ref ✔ 是 ✘ 不一定(可选) 修改已有变量的值,方法可读取和修改原值
out ✘ 否 ✔ 必须赋值 方法必须返回结果,调用方不关心初始值

一句话总结:

ref:带着已有值来,方法可改可不改; out:带着空碗来,方法必须填满才能返回。


一、ref ——「带着已有值进来」

使用 ref 需要满足:

  1. 调用前 变量必须初始化
  2. 方法内部 可以读取原值,也可以修改

例子:ref 修改外部变量

void Increase(ref int x)
{
    x = x + 10;
}

int a = 5;
Increase(ref a);
Console.WriteLine(a);  // 输出 15

解释: a 带着原始值 5 进入方法,方法内部增加 10,最终 a 的值被修改为 15。


二、out ——「来学习,必须学会才能出去」

使用 out 需要满足:

  1. 调用前 变量可以未初始化
  2. 方法内部 必须赋值,否则编译错误

例子:out 返回多个值

void GetHeroInfo(out string name, out int level)
{
    name = "张三";
    level = 9;
}

string heroName;
int heroLevel;

GetHeroInfo(out heroName, out heroLevel);

Console.WriteLine($"{heroName}, 等级 {heroLevel}");

输出:

张三, 等级 9

这是典型用法:方法返回多个结果,调用前变量无需初始化。


三、ref 与 out 的使用场景

ref 适合:

  • 修改已有外部变量
  • 方法可能读取原值
  • 用于性能优化或避免拷贝
  • 例:交换两个变量
void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

out 适合:

  • 方法需要“返回多个值”
  • 调用前变量没有意义
  • 常用于 TryPattern(如 int.TryParse
int.TryParse("123", out int number);

这里用 out 很合理,因为:

  • 输入没有意义(不需要初始化)
  • 方法必须返回结果给调用者

四、编译器要求总结

关键字 调用前必须初始化 方法内部必须赋值 方法是否可读取原值
ref ✔ 是 ✘ 不一定 ✔ 可读取
out ✘ 否 ✔ 必须 ✘ 不可读取

五、容易混淆的点

ref 错误示例

int x;
DoSomething(ref x);   // ❌ 编译错误,x 未初始化

必须:

int x = 0;
DoSomething(ref x);   // ✔

out 错误示例

void Test(out int x)
{
    // ❌ 编译错误:没有给 x 赋值
}

必须:

void Test(out int x)
{
    x = 10;  // ✔ 必须赋值
}

六、记忆口诀

ref:带着值进来,方法可读可改; out:带着空碗来,方法必须填满才能出去。


七、总结

  • ref:方法可以读取并修改已有值(双向传递),调用前必须初始化。
  • out:方法必须赋值给参数(单向输出),调用前可以不初始化,但方法内部不能读取原值。

换句话说:

  • ref = 我传入已有值,你可以读也可以改
  • out = 我传入空变量,你必须给它新值