• 关于引用类型的 ref 传参操作


    编码时候不自然的就给引用类型的参数加了个ref, 然后突然意识到: 加不加有区别吗? 做了些测试没区别啊....   参考了2篇文章, 最终结论放到图示里边了, 可能更好懂一些.

    文章一: 

    [转] 值类型 引用类型 ref out , 转自; --- http://blog.csdn.net/chuwachen/article/details/7416228

    值类型主要由两类组成:结构和枚举。结构分为以下几类:Numeric(数值)类型 (整型 浮点型 decimal)bool 用户定义的结构。基于值类型的变量直接包含值。将一个值类型变量赋给另一个值类型变量时,将复制包含的值。这与引用类型变量的赋值不同,引用类型变量的赋值只复制对对象的引用,而不复制对象本身。
    引用类型的变量又称为对象,可存储对实际数据的引用。包括:class interface delegate object string
    值类型变量直接包含其数据,这与引用类型变量不同,后者包含对其数据的引用。因此,向方法传递值类型变量意味着向方法传递变量的一个副本。方法内发生的对参数的更改对该变量中存储的原始数据无任何影响。如果希望所调用的方法更改参数的值,必须使用 ref 或 out 关键字通过引用传递该参数。

    当ref应用于值类型参数时,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
    当ref应用于引用类型参数时,允许被调用的方法修改该引用所引用的对象。
    当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值。但是无法更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存并使之在块外保持。若要这样做,应使用 ref 或 out 关键字传递参数。如
          void change(ref MyData data1, MyData data2)
          {
             data1.k = 6;
             data1 = new MyData(10);
             data2.k = 6;
             data2 = new MyData(10);
          }
          void Main(string[] args)
          {
             MyData data_1 = new MyData(8);
             MyData data_2 = new MyData(8);
             change(ref data_1, data_2);
             int k1 = data_1.k; // k1 = 10;
             int k2 = data_2.k; // k2 = 6;
          }

    传递到 ref 参数的参数必须最先初始化。这与 out 不同,out 的参数在传递之前不需要显式初始化。尽管 ref 和 out 在运行时的处理方式不同,但它们在编译时的处理方式是相同的。因此,如果一个方法采用 ref 参数,而另一个方法采用 out 参数,则无法重载这两个方法。

    =============

    文章二:

    [转] C#程序员请不要混淆引用类型和ref引用传参 --- 转自: http://bbs.51aspx.com/showtopic-43537.html

    C# ref引用传参
    先看一段代码1:

           

    static void Main(string[] args)

            {          

                StringBuilder sb = new StringBuilder("1");

                test(sb);

                Console.WriteLine(sb.ToString());

                Console.Read();

            }

            static void test(StringBuilder sb)

            {

                sb = new StringBuilder("2");

            }

    复制代码错误的观念: 程序输出"2",因为StringBuilder是引用类型,函数内部sb变量重新指向了托管堆中的新对象,函数返回后,外部的sb变量也指向了这个新对象,因为是引用类型吗,我传的是引用。

    在错误的观念中,认为 “ref引用传参” 仅对.net中的另一种基本类型--值类型有用。

      这种错误观念通常源于这样的经验,看代码2:


    static void Main(string[] args)

            {          

                StringBuilder sb = new StringBuilder("1");

                test(sb);

                Console.WriteLine(sb.ToString());

                Console.Read();

            }

            static void test(StringBuilder sb)

            {

                sb.Append("2");

            }

    复制代码
    我们通常会很自豪的说:“看吧,程序输出12,这就是引用类型的特点,如果换成值类型就不是了!”。我们得出的结论并没有错,实际上,这正是引用类型的特点!然而将这个观念扩大到代码1的情况,就错了!
    正确的理解:程序正确的输出是“1”,并没有因为StringBuilder是引用类型,就应该输出“2” 。如果要输出“2”,需要加ref:

           static void Main(string[] args)

            {          

                StringBuilder sb = new StringBuilder("1");

                test(ref sb);

                Console.WriteLine(sb.ToString());

                Console.Read();

            }

            static void test(ref StringBuilder sb)

            {

                sb = new StringBuilder("2");

            }

    复制代码


    对于ref传参,只要记住一点:对于值类型来说传的是值的地址,对于引用类型来说传的是地址的地址。

    对于引用类型,同样记住一点:引用类型本身的地址是一个值类型。就像我们学习c时,指针本身的地址就是一个int。

    好吧,用c来理解c#果然有点拗! 直观的理解:引用类型对象本身不改变,只改变对象的属性时,我们在操作同一个对象;如果连对象本身都可能会改变,就用ref传引用类型的对象吧!

    为什么不用strng作测试呢?
    因为string对象虽然是引用类型,但不能改变对象的属性CharArray,每次返回的都是新对象(看起来像值类型,其实不是!)。

    结论: 给张图吧

  • 相关阅读:
    报错:java.lang.IllegalStateException
    Eclipse中修改SVN用户名和密码方法
    部署服务器项目报错
    mybatis的双数据源创建
    SVN改地址eclipse怎么同步
    java中文乱码问题解决
    python3 内置函数
    python 生成器generator
    python 理解高阶函数
    python3 装饰器
  • 原文地址:https://www.cnblogs.com/cs_net/p/2683595.html
Copyright © 2020-2023  润新知