zoukankan      html  css  js  c++  java
  • 读<<CLR via C#>>总结(7) 以传引用的方式向方法传递参数ref&out

      默认情况下,CLR假定所有方法参数都是传值的。
      对于引用类型,对一个对象的引用(指向对象的一个指针)会传给方法,但是这个引用本身是以传值的方式传给方法的。方法能修改对象,调用者能看到这些修改。
      对于值类型,传给方法的是实例的一个副本。方法获得的是一个值类型实例副本,所以调用者中的实例不受影响
      代码如下:

    namespace refDemo2
    {
        class Program
        {
            static void Main(string[] args)
            {
                int i = 5;
                AddI(i);
                Console.WriteLine(i);//显示"5",i的值并没有改变
                Console.ReadKey();
            }
    
            private static void AddI(int v)//v获得的是i的一个副本,调用者中的实例不受影响
            {
                v+= 10;
            }
        }
    }

    一,为值类型使用ref和out

    namespace refDemo2
    {
        class Program
        {
            static void Main(string[] args)
            {
                int i = 5;
                AddI(ref i);
                Console.WriteLine(i);//显示"15",i的值被改变了
            Console.ReadKey();
            }
    
            private static void AddI(ref int v)//v获得的是一个指向实例对象(值5)的指针
            {
                v+= 10;
            }
        }
    }

    二,为引用类型使用ref和out

    namespace refDemo3
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s1 = "Tmac";
                string s2 = "Mcgrady";
    
                Swap(s1,s2);//没有使用ref
                Console.WriteLine(s1);//显示"Tmac"
                Console.WriteLine(s2);//显示"Mcgrady",为什么值没有交换呢???
            }
    
            private static void Swap(string a, string b)//a和b获取的是一个分别指向对象s1和s2的指针
            {
                string t = b;
                b = a;
                a = t;
            }
        }
    }

      容易困惑的地方:s1,s2是引用类型,传给方法Swap的肯定也是指向实例的一个指针,那理论上来讲调用了Swap方法之后s1和s2的值要交换呀,可是实际结果并不如我们所愿,这是为什么呢?
      答:就如文章一开头讲的,默认情况下,CLR假定所有方法参数都是传值的,虽然s1和s2是引用类型,调用方法时传递的也是指向实例的指针,但是,指针本身还是以传值方式传给方法的。所以调用者中实例的值并没有得到改变。

      要达到我们想要的效果,所以还是必须得使用ref,代码如下:

    namespace refDemo3
    {
        class Program
        {
            static void Main(string[] args)
            {
                string s1 = "Tmac";
                string s2 = "Mcgrady";
    
                Swap(ref s1,ref s2);
                Console.WriteLine(s1);//显示"Mcgrady"
                Console.WriteLine(s2);//显示"Tmac"
            }
    
            private static void Swap(ref string a,ref string b)//a和b获取的是一个分别指向对象s1和s2的指针
            {
                string t = b;
                b = a;
                a = t;
            }
        }
    }

     总结:1,从IL和CLR的角度看,ref和out是一样的,它们都会生成相同的IL代码,都导致传递指向实例的一个指针。

       2,ref一般用在方法内部对外部的值进行改变的时候。而out一般用在方法有多个返回值的时候。

  • 相关阅读:
    面试题:链表倒数第k个节点
    面试题:重建二叉树
    面试题:从尾到头打印链表
    面试题:第一个出现的字符位置
    面试题:调整数组顺序
    面试题:有限制条件的求和
    面试题:Fibonacci数列
    面试题:旋转数组的最小数字
    面试题:替换空格
    EndNote8破解版下载安装
  • 原文地址:https://www.cnblogs.com/mcgrady/p/2433403.html
Copyright © 2011-2022 走看看