值类型和引用类型
值类型:
基本数据类型、结构体和枚举是值类型
声明一个值类型,即把值类型压入线程栈
int num = 10;
拷贝值类型即将拷贝的值类型也压入线程栈
int num2 = num;
引用类型:
数组、类、委托、接口和已装箱的值类型是引用类型
声明一个引用类型,即把引用类型的实例对象压入托管堆,把托管堆中的实例对象的地址(引用、指针)压入线程栈
int[] array = new int[5];
拷贝引用类型,是拷贝引用类型在线程栈上的地址,地址仍然指向托管堆中的实例对象
int[] array2 = array;
使array2在线程栈上的地址置为null,而array地址指向的仍然是托管堆中的实例对象
array2 = null;
引用类型在托管堆里的实例对象可以存储着值类型,所以值类型不是只存储在线程栈里,引用类型的实例对象是只在托管堆里的。
值传递和引用传递(ref、out)
C#中方法的参数默认是值传递的,即方法中的局部变量是在线程栈中拷贝一份数据,值类型即拷贝一份值类型,引用类型则是拷贝一份引用类型在线程栈上的地址。
值传递
值传递值类型,修改局部变量的值,不会改变传入的参数
值传递引用类型,局部变量指向的内存地址和传入的参数是相同的,修改局部变量,参数也会改变。
public void Test(int num)
{
修改方法内的局部变量num,并不影响值类型
}
public void Test(int[] nums)
{
引用类型和局部变量指向同一地址,修改局部变量等同引用类型
}
引用传递
在值类型前加ref,即引用,使值类型引用传递,实现和引用类型相同的效果,在引用类型前加ref和没加是一样的。
public void Test(ref int num)
{
引用传递值类型,使值类型等同引用类型
}
public void Test(ref int[] nums)
{
引用传递引用类型,没有任何作用
}
引用传递都需要显示传递到方法。
ref 是有进有出,即能将参数传进去,函数里对变量的改变在函数结束时会改变值,因此需要在传递进去前初始化。
out 是只出不进,即将参数传进去时值是无效的,out会把参数清空,所以无法将一个值从 out 传递进去。
学习参考文章地址: