值类型和引用类型几乎囊括了c#中所有类型,重要性贯穿整个程序生涯,开发时间长短对于这两种类型理解深刻程度不同,但是开发中总要考虑到这两种类型的区别来使用。
那么什么是值类型?什么是引用类型呢?
——值类型(value type)
~值类型是一种将地址和值都存储在栈内,由系统自动释放的而指的实际值得一种数据类型。值类型的代表的是具体的值,在声明类型时候自动由线程开启一个内存,只占据极少内存。
~常见的值类型:整型:Int,长整型:long,布尔类型型:bool,浮点型:float,枚举:enum,结构体:struct。
~而所有所有的值类型都继承自System.ValueType,System.ValueType是继承于System.Object。所以可以说值类型间接继承于System.Object。
~修改值类型的属性会直接修改值,而且需要整体赋值,无法通过引用赋值。
——引用类型(reference type)
1 int i = 0; 2 int testValue(int temp) 3 { 4 temp = 4; return temp; 5 } 6 testValue(i); 7 Debug.Log(i);
1 int i = 0; 2 void testValue( ref int temp) 3 { 4 temp = 4; 5 } 6 testValue(ref i); 7 Debug.Log(i);
那么这个时候,i的值就变成了4。因为ref是将 i 的地址传递,此时变量temp和 i 引用的是同一个地址,那么修改地址的值,i 的值就会变化。
ps:ref和out是在传递参数时候传递值类型的地址,不同的是ref需要赋初始值,所以可以理解为ref是可进可出,out只出不进。
4、在赋值时候,值类型初始化后才能赋值。主要体现在结构体和类。
在这里简单列举下结构体和类的区别:
(1)构造函数:结构体构造必须带参,引用类型可带参,可不带参。
(2)定义字段:结构体只有加上static或者const才能赋初始值,引用类型可赋可不赋。
(3)默认:结构体默认是公有的,而类默认是私有的。
(4)可继承性:结构体不能被继承。
首先举例子说明值类型需要初始化赋值:
1 public class A 2 { 3 public int i = 0; 4 public double d = 0; 5 } 6 public struct B 7 { 8 public int i; 9 public double d; 10 } 11 public class test { 12 13 B GetB() 14 { 15 B b = new B(); 16 return b; 17 } 18 A GetA() 19 { 20 A a = new A(); 21 return a; 22 } 23 void Main() 24 { 25 GetB().i = 1;//这一行就会报错 26 GetA().i = 1; 27 } 28 }
报错信息:GetB返回值不是变量,是因为返回结构体是一个值,不同于引用类型返回了一个地址,直接通过地址查找子对象毫无问题。返回的结构体要想修改值,还需要一个变量去指向它。所以结构体里的子对象只能通过变量来修改,因为变量是一个具体的值。
——特殊的引用类型:string