• 【原创】理解C#的引用类型的值传递


    C#中,数据传递的方式有两种:按值传递和按引用传递,且默认情况下都是按值传递。而CLR支持两种基本类型为:值类型和引用类型。

    1. 当传递的参数为值类型,且数据传递方式为按值传递时,传递的是数据的一个拷贝。

    2. 当数据传递方式为按引用传递时,必须以ref或者out关键字来修饰。由于这部分不是本文主题,不做详细介绍,想了解相关内容可参见【原创】C#中ref和out的异同

    3. 当引用类型参数按值传递时,传递的是引用类型地址的数据拷贝。

    下面通过例子来验证第3点中所说

    先看以下示例代码:

    class Program
    {
    public static void Main()
    {
    var abf
    = new ArgsByRef();
    var abf1
    = abf;
    AddRef(abf);
    Console.WriteLine(abf.i);
    ReplaceRef(abf1);
    Console.WriteLine(abf.i);
    Console.WriteLine(abf1.i);
    }

    private static void AddRef(ArgsByRef abf)
    {
    abf.i
    = 20;
    Console.WriteLine(abf.i);
    }

    private static void ReplaceRef(ArgsByRef abf)
    {
    if (abf == null) throw new ArgumentNullException("abf");
    var m
    = new ArgsByRef();
    abf
    = m;
    Console.WriteLine(abf.i);
    }
    }

    public class ArgsByRef
    {
    public int i = 10;
    }

    现在开始来详细分析以上代码:

    1. var abf = new ArgsByRef(); 语句创建一个ArgsByRef实例abf,假设abf实例指向的堆中地址为0x1323。如图:

    2. var abf1 = abf; 语句创建一个ArgsByRef实例abf1,并将abf1实例的引用地址指向abf实例的引用地址,即abf1实例同样指向地址0x1323。

    3.

    AddRef(abf);
    private static void AddRef(ArgsByRef abf)
    {
    abf.i
    = 20;
    Console.WriteLine(abf.i);
    }

    执行AddRef方法时,传递abf实例作为参数。由于传递的是对象的引用,所以在方法内对对象的修改会直接影响对象。如图:

    4. 当执行ReplaceRef方法时,传递abf1实例作为参数,创建ArgsByRef实例m,假设实例m指向的堆地址为0x1345。如图:

    5. 当执行abf=m时,其实是创建了一个abf1实例引用地址的拷贝,使当前abf1实例的引用地址为0x1345。这里重点在于引用地址的拷贝,我画的表示图如下(不知道对与不对,还望大哥们多指点一下):

    6. 退出ReplaceRef方法,回到主方法后,由于是引用类型的引用地址的值传递,所以并没有改变对象的引用地址。实例abf1的引用地址仍为0x1323。

    所以abf1.i仍为20

    最后:说了这么多,也不知道描述清楚没有,如果有错误,还希望各位看官能不吝指点。我认为重点理解引用地址的拷贝。希望对大家理解值类型和引用类型,以及按值传递和按引用传递有帮助。

  • 相关阅读:
    2015-03-20——移动端UC浏览器、QQ浏览器自动全屏
    2015-03-18——mongodb的简单配置
    2015-03-12——简析DOM2级样式
    2015-03-12——简析DOM2级事件
    2015-03-11——简析DOM规范
    2015-03-10——简析javascript对象
    分页控件的编写
    Jquery添加掩盖层的插件
    正则表达式/g/i/d
    MVC请求生命周期
  • 原文地址:https://www.cnblogs.com/zwffff/p/1961585.html
Copyright © 2020-2023  润新知