引子
之前在开发一个功能模块时, 需要对数据进行一个统一的改动之后, 返回对象的同时, 还需要将一个状态值返回, 根据这个值, 再进行下一步的操作, 第一个想到的方法是使用 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 可以让我们更好的理解值类型和引用类型的区别.
来源: http://www.bubuko.com/infodetail-3719152.html