我们应该怎么去理解.net类型传递
如果按值传递引用类型,被调用者可能改变对象的状态数据的值,但不能改变所引用的对象。
如何理解以上两句话,首先我们先看一段代码:
先定义一个 Person 类,如下:
class Person { public string personName { get; set; } public int personAge { get; set; }public Person(string name, int age)
{ personName = name; personAge = age; } public Person() {}
public void Display() { Console.WriteLine("Name: {0},Age: {1}", personName, personAge); } }接着用添加一个方法: static void SendAPersonByValue(Person p) { p.personAge = 99; p.personName = "Nikki";p = new Person("Tom",100); //注意这句代码
}在 Main() 方法中写入代码: static void Main(string[] args) { Person fred = new Person("Fred",12); fred.Display();SendAPersonByValue(fred);
fred.Display(); }注意 p = new Person("Tom",100); 这行代码,SendAPersonByValue()按值传递 p,猜想一下输出结果。输出:Name: Fred,Age: 12
Name: Nikki,Age: 99由输出结果可以看出 SendAPersonByValue() 方法更改了对象的字段,Perosn p 不是按值传递吗,按值传递不是拷贝的副本吗,怎么会对对象进行更改呢?
而且 p = new Person("Tom",100); 这句代码似乎没起到任何作用。
回到文章顶部,如果按值传递引用类型,被调用者可能改变对象的状态数据的值,但不能改变所引用的对象。
书上是这样定义的,但是该怎么理解上面这句话呢?其实按值传递真正意义上是指传递栈上存储的值,当栈上存储的是值类型的变量时,传递的就是一个值的副本,因此对副本的更改不会导致原值的改变;当栈上存储的是一个地址(引用类型的变量)时,传递的就是这个地址的拷贝,它们指向托管堆上的同一个对象,当对托管堆上的对象更改时,自然会导致原对象的改变;而对变量本身进行更改时,更改的就是这个地址本身,因此不会导致原对象的改变。
用图来表示最适合不过了:
按值传递引用类型:
由图可知,对 p 本身更改并不影响 fred ,对p字段更改则会引起中字段的改变,因为它们指向同一个对象。
添加按引用传递的方法:
static void SendAPersonByReference(ref Person p) { p.personAge = 99;p = new Person("Tom",100); //注意这句代码
}修改 Main() 方法: static void Main(string[] args) { Person fred = new Person("Fred",12); fred.Display();SendAPersonByReference(ref fred);
fred.Display(); }输出:Name: Fred,Age: 12 Name: Tom,Age: 100按引用传递引用类型:如果按引用传递引用类型,被调用者可能改变对象的状态数据的值和所引用的对象。按引用传递引用类型:
按引用传递则是对栈中变量自身的地址进行拷贝(不是变量中存储的地址),因此不管是对其变量本身还是其指向的对象作更改都会导致原数据的改变。
以上纯属理解,不对的地方还请纠正,以便更改。