1.ref关键字
- 按引用传递参数,允许方法改变调用者传递的变量值。
- 调用前必须要初始化,否则会编译错误。
- 方法内部可以读取或修改参数的值。
int a = 10, b = 20;
Console.WriteLine($"a = {a},b = {b}");//输出a = 10,b = 20
Swap(ref a, ref b);
Console.WriteLine($"a = {a},b = {b}");//输出a = 20,b = 10
void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
使用场景:
- 需要内部修改传入的变量值
- 需要双向传递数据
2.out关键字
- 引用传递参数,但是要求方法内必须为参数赋值,否则会编译错误。
- 调用前无需初始化。
- 通常用于返回多个值的场景。
int a, b;
GetValue(out a, out b);
Console.WriteLine($"a = {a},b = {b}");
void GetValue(out int value1,out int value2)
{
value1 = 10;
value2 = 20;
}
使用场景:
- 实现类似TryParse的模式,返回操作状态,平且通过out返回结果。
- 需要方法返回多个值。
3.ref和out对比
相同点:
- 都是用于引用参数,允许方法内修改原始变量。
- 方法签名时必须显示使用ref和out,并且调用时候也要写明。
不同点:
| 特性 | ref | out |
|---|---|---|
| 初始化要求 | 调用前必须初始化变量 | 调用前无需初始化变量 |
| 方法内赋值要求 | 可以读取或修改变量值 | 必须在返回前赋值 |
| 设计意图 | 双向传递(输入+输出) | 单向输出(仅输出) |
| 典型用途 | 修改传入变量的值 | 返回额外结果(多返回值) |
4.注意点
Ⅰ.函数重载
-
虽然ref和out在方法标签中被视为不同,但是方法不能用ref和out来重载:
void Method(ref int a); void Method(out int b);//编译错误,无法重载
Ⅱ.值类型和引用类型
-
ref和out使用值类型时,是直接操作数据本身
-
在 C# 中,引用类型(如
class)的变量本身存储的是一个指向对象内存地址的引用。默认情况下,当引用类型作为参数传递给方法时,传递的是这个引用的副本(即“按值传递引用的副本”)。此时:- 你可以通过这个副本修改对象的内容(例如修改字段或属性),因为副本和原始引用指向的是同一个对象。
- 但你不能通过这个副本来修改原始引用本身(例如让原始变量指向一个新对象)。
而使用
ref或out时,传递的是原始引用变量的内存地址(即“按引用传递引用”),因此你不仅可以修改对象内容,还可以修改原始引用指向的对象! -
对于值类型比如Struct等,使用ref可以避免赋值数据的开销。
-
out参数可以在调用时声明变量
if(int.TryParse("100",out int number)){ Console.WriteLine(number); }