C#学习笔记:值类型与引用类型(详解)
这个问题应该是困扰任何一门语言初学者的问题,为此整理了网上的一些资料,希望能为大家解惑。
首先对于C#中的数据类型,只有两种,不是值类型就是引用类型。
值类型:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型
引用类型:数组,用户定义的类、接口、委托,object,字符串。
从表面的概念上看,值类型是直接存储其值,而引用类型存储的是对值的引用。
从存储在内存的位置来看,值类型是存储在堆栈(线程堆栈)上,而引用类型是存储在托管堆上。
(事实上,对于新手来说,也没有必要去细究堆栈和托管堆是什么,只需要知道是内存中的两块不同的区域就可以了,但为了保持严谨的治学态度,我建议大家可以参考:http://www.cnblogs.com/axzxs2001/archive/2008/08/28/1279037.html
)
讲这些内容还是比较晦涩的,下面通过一个示例讲解:
2
3 class SomeRef
4
5 {
6
7 public Int32 x;
8
9 }
10
11 //值类型SomeVal
12
13 struct SomeVal
14
15 {
16
17 public Int32 x;
18
19 }
20
21 static void ValueTypeDemo()
22
23 {
24
25 SomeRef r1 = new SomeRef();//在托管堆上分配
26
27 SomeVal v1 = new SomeVal();//在堆栈上分配
28
29 r1.x = 5; //提领指针
30
31 v1.x = 5; //在堆栈上实际修改
32
33 Console.WriteLine(r1.x); //显示5
34
35 Console.WriteLine(v1.x); //显示5
36
37
38
39
40 //以上代码为图的左边部分,以下代码为右边部分
41
42
43
44
45 SomeRef r2 = r1; //只复制引用()
46
47 SomeVal v2 = v1; //在堆栈上分配并复制成员
48
49 r1.x = 8; //修改r1.x和r2.x
50 v1.x = 9; //只修改v1.x而不修改v2.x
51 Console.WriteLine(r1.x); //8
52 Console.WriteLine(r2.x); //8
53 Console.WriteLine(v1.x); //9
54 Console.WriteLine(v2.x); //5
55
56 }
57
58
事实上通过这个示例,大家已经可以很清晰的区分值类型与引用类型的一些区别了,尤其关于赋值的问题:值类型赋值是通过值的复制来实现的,修改新的变量的值对原变量没有影响,而引用类型的赋值实际上是赋予给对象的引用,修改任何一个的值实际上修改了其引用,所有指向这个引用的变量的值都会发生改变。
但有时候你会发现这样的问题:
string s2 = s1;
Console.WriteLine(s1); //hello
Console.WriteLine(s2); //hello
s1="goodbye";
Console.WriteLine(s1); //goodbye
Console.WriteLine(s2); //hello
刚才我们也提到string类型属于引用类型,又根据引用类型值的特点,这里修改s1的值后,s2的值应该发生改变才对?
事实上这里并不矛盾,原因在于当改变s1的值是,实际上新创建了一个string对象,s1引用这个新的string对象;s2仍然引用原来string对象。产生这种行为的原因是string对象是恒定的,也就是说,一旦一个string对象被创建,它的值就不能再修改,所以当改变一个字符串变量的值的时候,仅仅是新创建了一个包含修改内容的新的string对象。这点大家要特别注意。
补充:
设计自己的类型时,是考虑使用值类型还是引用类型,某些时候,值类型比引用类型有更好的性能。以下几种情况应该考虑使用值类型:
(1)类型具有一个基元类型的行为,也就是这是一个非常简单的类型,其中没有成员会修改类型的任何字段。
(2)类型不需要从其它任何类型继承也不会派生出其它任何类型
(3)类型的实例较小,约为16字节或更小
(4)类型的实例较大,大于16字节,但不作为方法传递,也不作为方法的返回类型使用
参考文章:http://www.cnblogs.com/chenzehe/archive/2009/01/30/1381073.html
http://blog.csdn.net/canduecho/archive/2008/01/13/2042509.aspx
作者:Jason_z(开发者的网上家园 - 博客园)
出处:http://www.cnblogs.com/Jason_z/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。