值类型与引用类型:
1、引用类型为地址传递 ,值类型为值传递。这部分对于初学者来说不难理解。
2、ref 按引用传递参数,参数在进行使用前必须进行实例化。
部分同学会有疑问,引用类型已经是引用传递了传递的本来就是地址,没必要使用ref 关键字,但有一点没有考虑,如果地址变了呢?
一
public void Main()
{
int i = 0;
People _people = new People();
_people.Name = "张三";
Test(i, _people);
MessageBox.Show(_people.Name);
MessageBox.Show(i.ToString());
}
二
public void Test(int i, People people)
{
i = 7;
people.Name="李四";
}
如例一弹出值为 李四、0,people为引用传递,传递的是地址,例一、例二指向同一个地址,所以弹框显示李四;i为值类型传入的是具体值信息,不因例二的改变而改变,固弹框显示0。如果例二先进行实例化,赋值一个新地址信息,则例一不因例二的改变而改变。
public void Test(int i, People people)
{
i = 7;
people = new People();
people.Name = "李四";
}
如上,此时弹框显示张三。
public void Test(int i,ref People people)
{
i = 7;
people = new People();
people.Name = "李四";
}
如上,此时弹框又会显示李四。
以上为应用层面的解析。
底层原理分析:
1、值类型、引用类型的地址指针分配在线程栈上(内存空间的分配和释放由操作系统负责),引用类型实例分配在托管堆上(内存空间的分配和释放由垃圾回收器GC负责)。
2、释放方式不同:值类型在作用域内结束时,会被操作系统自释放,减少托管堆压力;引用类型则靠GC。因此值类型在性能上由优势。
3、属性不同,值类型是密封的,不能作为基类。引用类型一般具有继承性.。
4、初始化不同,值类型不能为null,默认初始化为该类型的默认值;引用类型默认初始化为null。
5、参数传递上的不同,值类型作为参数传递时,不影响本身。引用类型作为参数传递时,会改变最终该变量的值。
注:其实值类型存放在栈上也可能会存储在堆上,如果值类型定义在方法内部,存放在栈上,如果值类型是引用类型的成员变量,则存放在堆上。上述描述的值类型统一默认为定义在方法内部。