C#中使用ref和out传参的方法及区别

引子

之前在开发一个功能模块时,需要对数据进行一个统一的改动之后,返回对象的同时,还需要将一个状态值返回,根据这个值,再进行下一步的操作,第一个想到的方法是使用out参数修饰符,然后又查找了一下,发现可以使用ref和out都可以实现,那么这两种方法有哪些区别呢,查了一些资料之后,明白了用法,整理了一下,记录下来。

具体使用

ref的定义:MSDN的定义为:“The ref keyword indicates a value that is passed by reference.”就是通过引用来传递参数。ref也是Reference的缩写。了解了定义之后,ref怎么用呢?首先我们要明白值类型和引用类型的区别。这里的ref基本上就是服务于值类型的使用了。

上代码:

// 不使用 ref。
void Function(int num)
{
    num += 999;
}

var number = 1;
Function(number);
Console.WriteLine(number);
**// 输出 : 1;**

// 使用ref。
void Function(ref int num)
{
    num += 999;
}

var number = 1;
Function(ref number);
Console.WriteLine(number);

**//输出:1000**

看完代码就明白了:

  • 不使用ref的时候,方法接收到的变量值是1,然后在Function(int num)方法中,局部变量num做了累加之后,在方法执行完成之后就已经销毁了。number的值还是1。
  • 使用ref的时候,方法Function(ref int num)值收到的是number的地址,方法中执行的num+=999;此时相当于number+=999;直接修改了number地址的值,等于1000。

结论:ref参数修饰符,是通过给方法传递值类型的参数,将方法内的变量改变后带出方法外。

再看out参数。

out的定义:来自MSDN:“As a parameter modifier, which lets you pass an argument to a method by reference rather than by value.”“out”作为一个参数修饰符,允许您通过引用而不是通过值将参数传递给方法。

“In generic type parameter declarations for interfaces and delegates, which specifies that a type parameter is covariant.”在接口和委托的泛型类型参数声明中,它指定类型参数是协变的。

上代码:

// 不使用 out。
void Function(int num)
{
    num += 999;
}

var number = 1;
Function(number);
Console.WriteLine(number);
**// 输出 : 1;**
    
// 使用out。
void Function(out int num)
{
    num += 999;
}

var number = 1;
Function(out number);
Console.WriteLine(number);

**//输出:1000**

可以看出来,out和ref用法大差不差,几乎相同,out和ref其实都可以允许通过引用来传递参数。那么问题来了,既然ref 、out的作用看起来一样,为什么还定义了两个关键字呢,有何区别呢?区别就是,使用ref传递参数的时候,ref修饰的参数必须要有值,但是out可以使用一个未赋值的变量作为参数传递。

上代码:

void Function1(ref int num)
{
    num = 999;
}

void Function2(out int num)
{
    num = 999;
}

int number1;
int number2;
Function1(ref number1); // 此处会报错,ref修饰的参数必须要有值。
Function2(out number2); // 不会报错,out可以使用一个未赋值的变量作为参数传递。
Console.WriteLine(number1);
Console.WriteLine(number2);

另外需要注意一个点,对于引用类型,如果在方法体内使用了重新声明如使用new 等,此时引用类型的变量会产生一个新地址,方法内做修改等操作时并不会将对象的值传递出去,此时也可以使用ref或out,保持引用地址。

总结

当我们想将值类型在方法内部的的修改传递到外部时,可以使用ref或out修饰符,某些时候,引用类型的更改也可以使用ref或out来传递数据变更,ref和out可以让我们更好的理解值类型和引用类型的区别。

posted @ 2021-01-22 17:53  小xuo僧  阅读(230)  评论(0编辑  收藏  举报