zoukankan      html  css  js  c++  java
  • 基础:按值传递引用类型,按引用传递引用类新 细说并沉淀

          关于这个问题,有很多程序员不明白,并且在日常编程中经常会用到。比如:我在方法体外声明了一个变量,然后我想到一个方法体内改变

    这个值,然后到另外一个方法体内使用这个值。当然在我以前的一篇文章《基础:Out, params,ref 细说并沉淀》中有提到过,可以使用ref,或者Out来实现,只是当时没有将这个概括出来。没有将这个方法改成成以引用传递引用类型。

        接下来分别说明:

        先定义这么一个Person类

       1:    #region 按值传递引用类型 定义的一个Person类
       2:          public class Person {
       3:              private string _personName;
       4:              private int _personAge;
       5:   
       6:              #region Constructors
       7:              public Person(string name, int age) {
       8:                  this.PersonAge = age;
       9:                  this.PersonName = name;
      10:              }
      11:              public Person() {
      12:              }
      13:              #endregion
      14:   
      15:              #region Properties
      16:              public string PersonName {
      17:                  get { return _personName; }
      18:                  set { _personName = value; }
      19:              }
      20:              public int PersonAge {
      21:                  get { return _personAge; }
      22:                  set { _personAge = value; }
      23:              }
      24:              #endregion
      25:   
      26:              public void Display() {
      27:                  Console.WriteLine("Name:{0},Age:{1}", this.PersonName, this.PersonAge);
      28:              }
      29:          }
      30:          #endregion
     

      然后创建一个方法,将Person类的实体以值类型的形式传递进去

       1:   static void SendAPersonByValue(Person p) {
       2:              //改变p的年龄
       3:              p.PersonAge = 99;
       4:              //调用者能不能看到在方法体内的重新构造的对象?
       5:              p = new Person("YeanJay", 24);
       6:          }
     

       这样我们在Main中可以这样来调用这个方法:

       1:    //按照值传递引用类型
       2:              Person p = new Person("Ken", 23);
       3:              Console.WriteLine("调用方法之前:");
       4:              p.Display();
       5:              SendAPersonByValue(p);
       6:              Console.WriteLine("调用方法之后:");
       7:              p.Display();

    执行后的结果如下图:

        image

      这样可以看出,PersonAge的属性被改变了,似乎看起来违反了“按值”传递的语义。但是,这里传入的是引用,在复制的过程中,复制了指向调用者的对象的引用。

    在调用SendAPersonByValue()方法与调用者指向同一个对象,所以可以改变状态数据,但是在调用的方法体内,重新实例化,却是不可以的。

       接下来看下按照引用传递引用类型:

      同样使用上面的那个类,只是定义一个如下的调用方法:

       1:    #region 按照引用传递引用类型
       2:          static void SendAPersonByRef(ref Person p) {
       3:              p.PersonAge =27;
       4:              p = new Person("YeanJay", 24);
       5:   
       6:          }
       7:          #endregion

    这样在Main中将SendAPersonByValue(p);改成SendAPersonByRef(ref p);

    调用后的结果如下图:

       image

    显然,在使用ref之后,按照引用传递引用类型,在方法中可以改变传入的引用在内存中的指向。

      以下是Andrew Troelsen书中《Pro C# 2008 and .net 3.5 platform》中的关于按引用传递引用类型时候的黄金法则:

      1.如果按引用传递引用类型,被调用者可能改变对象的状态的值和所引用的对象;

       If a reference type is passed by reference, the callee may change the values of the object’s
       state data as well as the object it is referencing.

      2.如果按值传递引用类型,被调用者可能改变对象的状态数据的值,但不能够改变所引用的对象。

       If a reference type is passed by value, the callee may change the values of the object’s state
        data but not the object it is referencing.

  • 相关阅读:
    MySql 范式
    MySql 多表关系
    MySql 约束条件
    MySql 枚举和集合 详解
    【RoR win32】新建rails项目找不到script/server的解决办法
    【RoR win32】安装RoR
    【RoR win32】提高rails new时bundle install运行速度
    【bs4】安装beautifulsoup
    【py分析网页】可能有用的-re去除网页上的杂碎
    【pyQuery】抓取startup news首页
  • 原文地址:https://www.cnblogs.com/UpThinking/p/1628547.html
Copyright © 2011-2022 走看看