ref 和 out
目录
在 C# 中,方法参数默认是 值传递。
ref 和 out 是两个关键字,可以改变这一行为,使方法能够 直接修改外部变量。
二者核心区别
| 关键字 | 调用前必须初始化? | 方法内部必须赋值? | 用途 |
|---|---|---|---|
ref |
✔ 是 | ✘ 不一定(可选) | 修改已有变量的值,方法可读取和修改原值 |
out |
✘ 否 | ✔ 必须赋值 | 方法必须返回结果,调用方不关心初始值 |
一句话总结:
ref:带着已有值来,方法可改可不改; out:带着空碗来,方法必须填满才能返回。
一、ref ——「带着已有值进来」
使用 ref 需要满足:
- 调用前 变量必须初始化
- 方法内部 可以读取原值,也可以修改
例子: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 需要满足:
- 调用前 变量可以未初始化
- 方法内部 必须赋值,否则编译错误
例子: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= 我传入空变量,你必须给它新值