引用类型参数使用ref与不使用ref的区别

原创 2011年01月13日 16:27:00

我们都知道:

 

ref关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数的任何更改都将反映在该变量中。(摘自msdn)。

 

同时我们也可以在msdn上找到这样一段话:

 

按引用传递值类型(如本主题前面所示)是有用的,但是 ref 对于传递引用类型也是很有用的。这允许被调用的方法修改该引用所引用的对象,因为引用本身是按引用来传递的。下面的示例显示出当引用类型作为 ref 参数传递时,可以更改对象本身。

 

理解:不使用ref关键字引用类型的参数传递的是该对象(记为对象A)的引用,即对象A位于托管堆中的地址。而使用ref关键字的引用类型的参数传递的是该对象(记为对象B)引用的引用,即保存对象B位于托管堆中地址的变量(该变量位于堆栈中)的引用。即ref传递的是堆栈地址,而引用(引用类型的引用)传递的是托管堆的地址。当将ref使用在引用类型上,传递的是保存引用类型对象堆地址的栈地址,而不是堆地址。

 

下面用一个例子来对比使用ref和不适用ref的区别

 

源代码:

class Program
    {
        static void Main(string[] args)
        {
            A a1 = new A();
            a1.ID = 1;
            Console.WriteLine(string.Format("Main a1.ID: /t{0}", a1.ID));
            RefCall(ref a1);
            Console.WriteLine(string.Format("Main a1.ID: /t{0}", a1.ID));

            Console.WriteLine();

            A a2 = new A();
            a2.ID = 1;
            Console.WriteLine(string.Format("Main a2.ID: /t{0}", a2.ID));
            Call(a2);
            Console.WriteLine(string.Format("Main a2.ID: /t{0}", a2.ID));

            Console.Read();
        }

        static void RefCall(ref A a)
        {
            a.ID = 2;
            Console.WriteLine(string.Format("RefCall a.ID: /t{0}", a.ID));
            a = new A();
            Console.WriteLine(string.Format("RefCall a.ID: /t{0}", a.ID));
        }

        static void Call(A a)
        {
            a.ID = 3;
            Console.WriteLine(string.Format("Call a.ID: /t{0}", a.ID));
            a = new A();
            Console.WriteLine(string.Format("Call a.ID: /t{0}", a.ID));
        }
    }

    class A
    {
        private int id = 0;
        public int ID
        {
            get { return this.id; }
            set { this.id = value; }
        }
    }

 

运行结果:

Main a1.ID: 1
RefCall a.ID: 2
RefCall a.ID: 0
Main a1.ID: 0

 

Main a2.ID: 1
RefCall a.ID: 3
RefCall a.ID: 0
Main a2.ID: 3

 

通过运行结果我们可以知道使用ref关键字传递参数的方法改变了Main函数中的变量(这里为a1),而不适用ref关键字的方法没有改变Main函数中的变量(这里为a2)。

 

至此我们就应该对引用类型使用和不使用ref关键的区别一目了然了。

C#引用类型参数加ref或out与不加ref或out的区别

 如果不用ref传递的是原引用变量的副本,即把原来的引用变量复制一分传递给方法; 如果用ref传递的是原引用变量的引用.    class   a     {           i...
  • XueminXu
  • XueminXu
  • 2014年09月02日 15:36
  • 905

C#中引用类型做方法参数时,加ref或out,与不加ref或out到底有什么区别?

如果不用ref传递的是原引用变量的副本,即把原来的引用变量复制一分传递给方法;如果用ref传递的是原引用变量的引用.   class   a     {           int   val;   ...
  • andy_212
  • andy_212
  • 2009年04月08日 13:33
  • 2996

value和ref的区别

ref和value的区别ref即引用,ref="dataSource"就是引用dataSource的beanvalue直接设置一个值ref,spring容器会在引用后进行验证,验证当前的xml是否存在...
  • sethwiseman
  • sethwiseman
  • 2017年08月10日 12:43
  • 707

C#中为何要使用ref参数 (个人理解)

前言 这篇文章并不是想说明,ref的使用或者和out参数的区别等等 而是对C#为什么要放入ref参数给出一些我的个人理解 我也是初学C#,查阅了一些资料给出的个人理解,如果哪里有问题,也欢迎大家不吝赐...
  • luke2834
  • luke2834
  • 2016年01月21日 19:51
  • 955

spring框架怎么选择使用ref和value?

一般赋值或者加载配置文件的的时候使用value,引用或者注入的时候使用ref
  • mr_array
  • mr_array
  • 2017年03月10日 17:31
  • 1377

ref和out的作用和区别

相同点:方法的定义和调用都必须显示使用ref、out关键字。都会导致参数按引用传递。 不同点:传递给ref关键字的参数必须赋初始值,而out不用。out关键字会清空变量,即使变量已经赋值也不行,...
  • fox123871
  • fox123871
  • 2014年08月07日 23:51
  • 1265

spring中用ref属性指定的三种方法

package javamxj.spring.basic.ref; public class HelloBean {     private String hello;     publ...
  • chenpeng19910926
  • chenpeng19910926
  • 2015年12月14日 20:25
  • 2158

fastjson 如何去掉 $ref,使用方法,不讲原理

fastjson 是一个 不错的json格式化工具, 但是在使用时,如果 碰到统一地址对象引用,就会用$ref替代 。 怎么去掉ref呢, 这里 有两种方法 1. 使用  SerializerFeat...
  • jianojian
  • jianojian
  • 2017年02月16日 14:46
  • 918

C# out、ref关键字的用法和区别

说说自己对out、ref的认识,面试问到的几率很高哟。 out: class Program { /* * out、ref都是引用传递,传递后使用...
  • CommandBaby
  • CommandBaby
  • 2016年04月06日 14:53
  • 3869

C# ref与out 引用和传值的区别

C# 中,既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员更改参数的值,并保持该更改。若要通过引用传递参数, 可使用ref或out关键字。ref和out这两个关键字都能够提供相似的功效...
  • u013192061
  • u013192061
  • 2015年03月04日 09:06
  • 776
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:引用类型参数使用ref与不使用ref的区别
举报原因:
原因补充:

(最多只允许输入30个字)