C# 中ref 与 out 总结

  参数的传递一般分为两种:一种是“值传递”即:传递实参的拷贝,既然是拷贝那么在函数中对这个形参所作的任何动作都不会反映到原来的实参中。另外一种是“引用传递”即:传递实参的地址(形参和实参指向同一块内存地址),那么在函数中对形参所作的任何改变都要反映到原来的实参中。

  在C#中实现“引用传递”的两种方式为:ref 和 out。当然这两种方式也有他们的不同,下面将逐步讲解他们的不同之处。

  1. 使用ref关键字进行“引用传递”时,传入的实参必须先被初始化,这就像C和C++中的指针一样,一定要先给它赋值(让它指向一个指定的内存位置),要不然它不一定会指向内存的哪里,这样很危险,不允许。而使用out关键字进行“引用传递”时,传入的实参不必先初始化。如下面的例子所示:
    复制代码
        
        
    1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace RefAndOut 7{ 8 class RefAndOutTesting 9 { 10 static void Main(string[] args) 11 { 12 int x; 13 int y; 14 OutTest(out x, out y); 15 Console.WriteLine(string.Format("x = {0}, y = {1}", x, y)); 16 17 int a = 100; 18 int b = 200; 19 RefTest(ref a, ref b); 20 Console.WriteLine(string.Format("a = {0}, y = {1}", a, b)); 21 } 23 //out参数在使用前不必初始化 24 public static void OutTest(out int first, out int second) 25 { 27 first = 1; 28 second = 2; 29 } 30 //ref参数在使用前必须初始化 31 public static void RefTest(ref int first, ref int second) 32 { 33 first = 1111; 34 second = 2222; 35 } 36 } 37}
    复制代码

     

  2. 虽然使用out关键字进行“引用传递”时,传入的实参不必先初始化,但是在函数中一定要先对参数进行初始化,之后再使用。因为:在使用out参数的时候,程序首先将out的实参(形参)置空,(因此实质上实参先初始化了对此函数也没有用)然后再对参数进行相应的操作;由于置空了,所以在离开该函数之前必须完成参数的初始化(即使你不对参数做任何操作),要不然该参数的指针又不知道该指向何处了。假如变化一下上面的OutTest函数:
    复制代码
        
        
    1 public static void OutTest(out int first, out int second) 2 { 3 first = second; 4 //first = 1; 5 //second = 2; 6   }
    复制代码
    便会提示你:Use of unassigned out parmeter 'second'。即使你先初始化实参再去调用也会出现同样的错误(原因就是out先对参数进行清空操作)
    复制代码
        
        
    1 using System; 2   using System.Collections.Generic; 3   using System.Linq; 4   using System.Text; 5 6   namespace OutAndRef 7 { 8 class Program 9 { 10 static void Main( string [] args) 11 { 12 // out变量在使用之前不必进行显示的赋值 13 int x = 1111 ; 14 int y = 2222 ; 15 OutTest( out x, out y); 16 Console.WriteLine( " x = {0}, y = {1} " , x, y); 17 } 18 20 public static void OutTest( out int first, out int second) 21 { 22 // 离开这个函数前,必须对first和second赋值,否则会报错。 23 first = second; 24 // 上面这行会报错,因为使用了out后,first和second都清空了,需要重新赋值,即使调用函数前赋过值也不行 25 first = 1 ; 26 second = 2 ; 27 } 29 } 31 } 32
    复制代码

     

  3. 因此上面的两点可以总结为:ref有出有进,out有出没进。
  4. 使用ref和out进行“引用传递”,在定义方法和调用方法时,都要在参数前加ref和out关键字,以满足匹配。
  5. 由于属性是方法,不是变量;而指针是变量。所以属性都不可以作为ref和out参数传递。如果在上面的RefAndOutTesting类中声明两个属性,传递给RefTest和OutTest方法中,则会出错!
    复制代码
        
        
    1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace RefAndOut 7 { 8 class RefAndOutTesting 9 { 10 //属性(是方法,不是变量)所以不可以作为ref和out参数 11 public static int firstNumber 12 { 13 get; 14 set; 15 } 16 public static int secondNumber 17 { 18 get; 19 set; 20 } 21 22 //字段可以作为ref和out参数 23 public static int myNumber; 24 public static int yourNumber; 25 26 static void Main(string[] args) 27 { 28 //正确 29 OutTest(out myNumber, out yourNumber); 30 Console.WriteLine(  "myNumber = {0}, yourNumber = {1}", myNumber, yourNumber); 31 RefTest(ref myNumber, ref yourNumber); 32 Console.WriteLine( "myNumber = {0}, yourNumber = {1}", myNumber, yourNumber); 33 34 //错误 35 OutTest(out firstNumber, out secondNumber); 36 Console.WriteLine("firstNumber = {0}, secondNumber = {1}", firstNumber, secondNumber); 37 RefTest(ref firstNumber, ref secondNumber); 38 Console.WriteLine("firstNumber = {0}, secondNumber = {1}", firstNumber, secondNumber); 45 } 46 } 47 } 48
    复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值