值类型
值类型变量声明之后,编译器会为其在栈中分配好预定义的的内存空间。
值类型包括:byte,short,int,long,float,double,decimal,char,bool,struct,enum
引用类型
当声明一个引用类型时,只会在栈中分配一个用于容纳地址的内存,并在数据引用期间将存储在堆中的数据的地址保存在栈的内存中。
引用类型包括:object,string,class,interface,delegate,一维和多维数组
需要注意的特殊类型:
(1)字符串对象(string)是比较特殊的引用对象,因为它看起来就跟值对象一样,但是其实对它的赋值、合并、分割操作并不是在原有的字符串中进行操作,而是返回一个新的字符串对象,string的对象被分配在堆上,而不是在栈上。
(2)数组对象(Array)是引用对象,在赋值的时候实际返回的是对源对象的另一份引用。如果是想要真正的复制,则需新建一份数组对象,并将源数据逐一拷贝到新的数组对象中。
如果同时将数据赋值给值类型和引用类型,修改原来的数据只会影响引用类型,如下:
class RefData//引用类型
{
public int a;
}
struct ValData//值类型
{
public int a;
}
……
RefData r1 = new RefData();//在堆上分配
ValData v1 = new ValData();//在栈上分配
r1.a = 1;
v1.a = 1;
Console.WriteLine("r1={0},v1={1}", r1.a, v1.a);
RefData r2 = r1;//修改r1,r2会变
ValData v2 = v1;//修改v1,v2不会变
r1.a = 2;
v1.a = 3;
Console.WriteLine("r1={0},v1={1}", r1.a, v1.a);
Console.WriteLine("r2={0},v2={1}", r2.a, v2.a);
Console.ReadLine();
运行结果:r1=1,v1=1
r1=2,v1=3
r2=2,v2=1
装箱与拆箱
简单的来说,装箱是将值类型转换为引用类型(object),拆箱是将引用类型(object)转换为值类型。
装箱实例
int val = 1;//值类型
object obj = val;//转换为引用类型
Console.WriteLine("{0}", obj);
拆箱实例
int val = 100;//值类型
object obj = val;//转换为引用类型
int num = (int)obj;//转换为值类型
Console.WriteLine("{0}", obj);
注:只有被装过箱的对象才能被拆箱。
参考博客:https://blog.youkuaiyun.com/qiaoquan3/article/details/51439726