ref和out关键字

53 阅读2分钟

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 = 10void 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,并且调用时候也要写明。

不同点:

特性refout
初始化要求调用前必须初始化变量调用前无需初始化变量
方法内赋值要求可以读取或修改变量值必须在返回前赋值
设计意图双向传递(输入+输出)单向输出(仅输出)
典型用途修改传入变量的值返回额外结果(多返回值)

4.注意点

Ⅰ.函数重载
  • 虽然ref和out在方法标签中被视为不同,但是方法不能用ref和out来重载:

    void Method(ref int a);
    void Method(out int b);//编译错误,无法重载
    
Ⅱ.值类型和引用类型
  • ref和out使用值类型时,是直接操作数据本身

  • 在 C# 中,引用类型(如 class)的变量本身存储的是一个指向对象内存地址的引用。默认情况下,当引用类型作为参数传递给方法时,传递的是这个引用的副本(即“按值传递引用的副本”)。此时:

    • 你可以通过这个副本修改对象的内容(例如修改字段或属性),因为副本和原始引用指向的是同一个对象。
    • 但你不能通过这个副本来修改原始引用本身(例如让原始变量指向一个新对象)。

    而使用 refout 时,传递的是原始引用变量的内存地址(即“按引用传递引用”),因此你不仅可以修改对象内容,还可以修改原始引用指向的对象!

  • 对于值类型比如Struct等,使用ref可以避免赋值数据的开销。

  • out参数可以在调用时声明变量

    if(int.TryParse("100",out int number)){
        Console.WriteLine(number);
    }