《叩响C#之门》第六章 函数 地址传递一节中遇到的疑问和解决 (建议修改书中原文)
读到本章,习惯性的编了点代码做试验,发现一个疑问,在6.4.2地址传递中,书中提到“当参数类型为数组、结构体等复杂类型时,并不是将实参完整的复制一份给形参,而是把实参的地址传给形参即实参和形参指向同一块内存空间,这种传递叫地址传递”。
读到此,当时就觉得有点困惑,在印象中,struct是值类型,怎么可能在值传递中传递的是指向实例(值类型的参数也应可称为实例吧)的地址呢?为此又特地做了如下代码的试验,发现struct在值传递时,确实不能进行地址传递。
后来,又往后翻看了第七和第八章,特别是对值类型、引用类型的介绍,使我受益匪浅,回过头看第六章此处时,更觉得书中的此处应该编辑为:
1、值传递分为两种类型
1)参数为值类型时的值传递
此时,传递的是实例拷贝,形参不会改变实参。
2)参数为引用类型的值传递
此时,就如同书中提到的地址传递,但绝对不是复杂类型才这样用,而是引用类型的参数才能进行地址传递,传递的也是值拷贝,只不过此情况下的值拷贝是引用类型实例的地址而已(也可以说传递的是对象的引用符)!
2、后面的引用型参数(ref),我觉得也应该再拓展一些,用ref传递的是参数的地址
1)ref后面跟值类型时,传递的是值类型的地址
2)ref后面跟引用类型时,传递的是对象的引用符的地址!
说明struct作为参数传递的不是地址的例子:
using System; using System.Collections.Generic; namespace Test { public class Program { static void Main() { Student student1=new Student(0001,"TOM","Male"); DisplayStudent(student1); Student student3=ChangeStudent(student1); DisplayStudent(student3); DisplayStudent(student1); } public static Student ChangeStudent(Student studentVar) { studentVar.Number = 0002; studentVar.Name = "Mike"; studentVar.Sex = "Male"; DisplayStudent(studentVar); Student student3; student3 = studentVar; student3.Number = 0003; student3.Name = "Rose"; student3.Sex = "Female"; return student3; } public static void DisplayStudent(Student studentVar) { Console.WriteLine("{0:0000} {1} {2}", studentVar.Number, studentVar.Name, studentVar.Sex); } } public struct Student { private int number; private string name; private string sex; public Student(int numVar,string nameVar,string sexVar) { this.number = numVar; this.name = nameVar; this.sex = sexVar; } public int Number { get { return this.number; } set { this.number = value; } } public string Name { get { return this.name; } set { this.name = value; } } public string Sex { get { return this.sex; } set { this.sex = value; } } } }
输出:
最后一行是最开始的struct的值,经过参数传递后,没有改变!
把struct 改成class,让其成为引用类型再试一下(即将public struct Student 直接改为public class Student ),输出如下
引用类型为参数,传递后,值改变了