引用和值传递
在值类型和引用类型中已经谈到过这类东西。但是这次再深入说说
方法参数
方法参数默认是按值传递的,可以看作是一种副本
- 值类型就是传递一个值类型的副本
- 引用类型就是传递一个引用(即对象地址)的副本
这样,作为局部变量的副本们,就会在函数体执行完毕之后被栈释放掉
由于值类型的传递比较简单,如果需要修改等,直接使用ref, out, in等关键字就好,已经在值类型和引用类型中提及,不再赘述。
考虑
假设有一个Person类型,封装了Name属性;我们需要修改它
C#
public void Modify(Person p) => p.Name = "Alice"此时传入的p是对传入对象引用的拷贝,也就是说和原对象指向同一块堆区的内存空间,所以直接修改p,就会对原始数据产生影响
C#
public void Modify(Person p)
{
Person temp = new("Alice");
p = temp;
}
public void Modify(Person p) => p = new Person("Alice")以上两种写法,都是把传入的副本p重新指向一块新的空间,这种写法是错误的,它并不会改变原始对象的引用所指向的位置(简单来说,这样写不会达到修改名字的效果)
方法被调用时,CLR 会把该引用的值复制一份到方法的参数槽里(这是参数的局部变量 p)。现在有两个引用值:调用方的引用仍然是 A,方法内部的 p 也是 A(但它们是两个独立的变量,存储相同的地址值)。
进行一个理解,假设原始引用是Person tom = new Person("Tom")
tom -> Person("Tom")那么在调用方法的时候会出现 ——
tom, p -> Person("Tom")也就是二者都指向同一块内存
现在执行函数体的时候
tom -> Person("Tom")
p -> Person("Alice")此时二者已经不是指向同一块地址了(tom是tom,p是p 所以并不相关,便可以解释此时对于p的修改并不会修改到tom所指向的数据