基础:按值传递引用类型,按引用传递引用类新

来源:互联网 发布:java表名无效 编辑:程序博客网 时间:2024/05/17 07:42

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

这个值,然后到另外一个方法体内使用这个值。当然在我以前的一篇文章《基础: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.

0 0
原创粉丝点击