您的位置:首页 > 编程语言 > C#

C# ref和out

2014-03-29 13:29 330 查看
方法参数上的   ref   方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。若要使用  
ref   参数,必须将参数作为   ref   参数显式传递到方法。ref   参数的值被传递到   ref   参数。传递到   ref   参数的参数必须最先初始化。将此方法与   out   参数相比,后者的参数在传递到  
out   参数之前不必显式初始化。  属性不是变量,不能作为   ref   参数传递。   
    
  如果两种方法的声明仅在它们对   ref   的使用方面不同,则将出现重载。但是,无法定义仅在   ref   和   out   方面不同的重载。例如,以下重载声明是有效的:
  class   MyClass     
  {   
        public   void   MyMethod(int   i)   {i   =   10;}   
        public   void   MyMethod(ref   int   i)   {i   =   10;}   
  }   
  但以下重载声明是无效的:   
  class   MyClass     
  {   
        public   void   MyMethod(out   int   i)   {i   =   10;}   
        public   void   MyMethod(ref   int   i)   {i   =   10;}   
  }   
方法参数上的   out   方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。当希望方法返回多个值时,声明  
out   方法非常有用。使用   out   参数的方法仍然可以返回一个值。一个方法可以有一个以上的   out   参数。  若要使用   out   参数,必须将参数作为   out   参数显式传递到方法。out  
参数的值不会传递到   out   参数。不必初始化作为   out   参数传递的变量。然而,必须在方法返回之前为   out   参数赋值。 属性不是变量,不能作为  
out   参数传递。如果两个方法的声明仅在   out   的使用方面不同,则会发生重载。不过,无法定义仅在   ref   和   out   方面不同的重载。例如,以下重载声明是有效的:   
  class   MyClass     
  {   
        public   void   MyMethod(int   i)   {i   =   10;}   
        public   void   MyMethod(out   int   i)   {i   =   10;}   
  }   
  而以下重载声明是无效的:   
  class   MyClass     
  {   
        public   void   MyMethod(out   int   i)   {i   =   10;}   
        public   void   MyMethod(ref   int   i)   {i   =   10;}   
  }

..................

...........

.......................

........

//上面的理解起来非常不好理解。下面我说说我自己的看法。

首先:两者都是按地址传递的,使用后都将改变原来的数值。很多人在论坛上解释说out是按数值传递,是错误的。简单的测试后可以知道out使用也能改变数值的,所以肯定是按照地址传递的。

其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是两个的区别,或者说就像有的网友说的,ref是有进有出,out是只出不进。经典!!!

需要指出的是:
1、当我们频繁传递大型参数的时候,比如说DataTable、DataSet...的时候,会节省好多内存资源。
2、当我们想得到方法多样化的处理结果的时候,而我们又不愿意复杂化方法所返回的结果,那么我们可以在方法里定义多个ref 或者 out,以期得到丰富的结果。比如说,我们调用一个方法,要同时得到string、int、double、bool、Array...等几种不同类型的结果,而return返回object又很复杂的时候,ref 和
out的处理效果,看上去将会是多么的赏心悦目...


原则:在被调用函数内,out引入的参数在返回前至少赋值一次,否则编译器将提示:使用了未赋值的out参数;

           在被调用函数内,ref引入的参数在返回前不必为其赋初值。

总结:C#中的ref和out提供了值类型按引用进行传递的解决方案,当然引用类型也可以用ref和out修饰,但这样已经失去了意义。因为引用数据类型本来就是传递的引用本身而非值的拷贝。ref和out关键字将告诉编译器,现在传递的是参数的地址而不是参数本身,这和引用类型默认的传递方式是一样的。同时,编译器不允许out和ref之间构成重载,又充分说明out和ref的区别仅是编译器角度的,他们生成的IL代码是一样的。有人或许疑问,和我刚开始学习的时候一样的疑惑:值类型在托管堆中不会分配内存,为什么可以按地址进行传递呢?值类型虽然活在线程的堆栈中,它本身代表的就是数据本身(而区别于引用数据类型本身不代表数据而是指向一个内存引用),但是值类型也有它自己的地址,即指针,现在用ref和out修饰后,传递的就是这个指针,所以可以实现修改后a,b的值真正的交换。这就是ref和out给我们带来的好处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: