跟风写博---也谈值类型和引用类型
在博客园潜水一年多,半年前开了博,但一直闲置着,前阵子看了老赵的博客二三事后,终于下了决定要认真写几篇。正巧最近园子在讨论“值类型和引用类型”相关的话题,我就谈谈个人见解。
直接从实际代码出发,先看第一段代码。
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 int x = 1;
6 int y = x;
7 y = 2;
8
9 TestClass classX = new TestClass();
10 classX.Number = 1;
11
12 TestClass classY = classX;
13 classY.Number = 2;
14
15 Console.WriteLine("x:" + x);
16 Console.WriteLine("y:" + y);
17
18 Console.WriteLine("classX.Number:" + classX.Number);
19 Console.WriteLine("classY.Number:" + classY.Number);
20
21 }
22
23 public class TestClass
24 {
25 public int Number { get; set; }
26 }
27 }
其中int为值类型,class为引用类型。运行代码得到的结果为:
x:1
y:2
classX.Number:2
classY.Number:2
可以看到,值类型x赋值给y,修改y的值,x不变。引用类型classX赋值给classY,修改classY的属性值,classX的属性值也跟着改变。
再看一段代码:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 TestStruct structX = new TestStruct();
6 structX.Number = 1;
7
8 AddStruct(structX);
9
10 Console.WriteLine("structX.Number:" + structX.Number);
11
12 TestClass classX = new TestClass();
13 classX.Number = 1;
14 AddClass(classX);
15
16 Console.WriteLine("classX.Number:" + classX.Number);
17
18 }
19
20 public class TestClass
21 {
22 public int Number { get; set; }
23 }
24
25 public struct TestStruct
26 {
27 public int Number { get; set; }
28 }
29
30 public static void AddClass(TestClass testClass)
31 {
32 testClass.Number += 1;
33 }
34
35 public static void AddStruct(TestStruct testStruct)
36 {
37 testStruct.Number += 1;
38 }
39 }
分别将值类型structX和引用类型classX当做参数传入到对应的方法,在方法中将Number属性值加1。运行代码得到的结果为:
structX.Number:1
classX.Number:2
结果表明,经过方法执行后,值类型structX的属性值没变,而引用类型的属性值变了。
对照实验结果,我们看一下两种类型在内存中的定义:
值类型实例通常分配在线程的堆栈(stack)上,并且不包含任何指向实例数据的指针,变量本身就包含了其实例数据。
引用类型实例分配在托管堆(managed heep)上,变量保存了实例数据的内存引用。
在我看来引用类型就像是c++中的指针,当引用类型赋值给一个变量实际上赋值的是指向数据的内存引用地址。
回头来分析第一段代码,classX赋值给classY,相当于把内存引用赋值给classY,两个变量指向同一个地址,所以当classY的Number值修改时,classX的值也跟着改变。
同理分析第二段代码,当把引用类型作为参数传递给方法时,传递的是实际数据的内存引用。当方法内部修改了内存引用指向的实际数据时,classX的值也会发生变化。
知道了值类型和引用类型上的区别以后,来了解一下哪些是值类型,哪些是引用类型。
.NET中的值类型有:byte,short,int,long,float,double,decimal,char,枚举enum,结构struct等。
引用类型有:object,string,class,interface,数组int[],委托delegate等。
其中最特殊的是引用类型string,在上面第一段代码中,将class改为string类型,结果和值类型int相同。为了方便理解,暂且把string看做是可以为null的值类型吧。
至于string为何特殊,特殊在何处,园子早期有很多优秀的文章,都可以翻来看,这里不做深入探讨,我推荐王涛的书《你必须知道的。NET》,这本书已经停印,不过淘宝可以买到复印版的,价格便宜一半(不鼓励买盗版,但这是买不到正版的无奈选择^_^)。也可以直接去看他博客里的系列文章。
接下来会尝试着写一些值类型和引用类型在实际项目中的应用和技巧,例如值类型加问号变成引用类型如int?,ref 和 out 关键字的使用等。希望能在"值类型和引用类型"这个已经写烂的话题里挖出一些自己的东西。
声明:个人博客已迁移到Github此处,新博客内容大多与前端技术相关。