C#学习笔记:值类型与引用类型(详解)


这个问题应该是困扰任何一门语言初学者的问题,为此整理了网上的一些资料,希望能为大家解惑。

首先对于C#中的数据类型,只有两种,不是值类型就是引用类型。

值类型:结构体(数值类型,bool型,用户定义的结构体),枚举,可空类型

引用类型:数组,用户定义的类、接口、委托,object,字符串。

从表面的概念上看,值类型是直接存储其值,而引用类型存储的是对值的引用。

从存储在内存的位置来看,值类型是存储在堆栈(线程堆栈)上,而引用类型是存储在托管堆上。

(事实上,对于新手来说,也没有必要去细究堆栈和托管堆是什么,只需要知道是内存中的两块不同的区域就可以了,但为了保持严谨的治学态度,我建议大家可以参考:http://www.cnblogs.com/axzxs2001/archive/2008/08/28/1279037.html


讲这些内容还是比较晦涩的,下面通过一个示例讲解:

 1C#学习笔记:值类型与引用类型(详解)//引用类型SomeRef
 2C#学习笔记:值类型与引用类型(详解)
 3C#学习笔记:值类型与引用类型(详解)    class SomeRef
 4C#学习笔记:值类型与引用类型(详解)
 5C#学习笔记:值类型与引用类型(详解)C#学习笔记:值类型与引用类型(详解)  {
 6C#学习笔记:值类型与引用类型(详解)
 7C#学习笔记:值类型与引用类型(详解)        public Int32 x;
 8C#学习笔记:值类型与引用类型(详解)
 9C#学习笔记:值类型与引用类型(详解)    }

10C#学习笔记:值类型与引用类型(详解)
11C#学习笔记:值类型与引用类型(详解)    //值类型SomeVal
12C#学习笔记:值类型与引用类型(详解)
13C#学习笔记:值类型与引用类型(详解)    struct SomeVal
14C#学习笔记:值类型与引用类型(详解)
15C#学习笔记:值类型与引用类型(详解)C#学习笔记:值类型与引用类型(详解)  {
16C#学习笔记:值类型与引用类型(详解)
17C#学习笔记:值类型与引用类型(详解)        public Int32 x;
18C#学习笔记:值类型与引用类型(详解)
19C#学习笔记:值类型与引用类型(详解)    }

20C#学习笔记:值类型与引用类型(详解)
21C#学习笔记:值类型与引用类型(详解)    static void ValueTypeDemo()
22C#学习笔记:值类型与引用类型(详解)
23C#学习笔记:值类型与引用类型(详解)C#学习笔记:值类型与引用类型(详解)  {
24C#学习笔记:值类型与引用类型(详解)
25C#学习笔记:值类型与引用类型(详解)        SomeRef r1 = new SomeRef();//在托管堆上分配
26C#学习笔记:值类型与引用类型(详解)
27C#学习笔记:值类型与引用类型(详解)        SomeVal v1 = new SomeVal();//在堆栈上分配
28C#学习笔记:值类型与引用类型(详解)
29C#学习笔记:值类型与引用类型(详解)        r1.x = 5;                  //提领指针
30C#学习笔记:值类型与引用类型(详解)
31C#学习笔记:值类型与引用类型(详解)        v1.x = 5;                  //在堆栈上实际修改
32C#学习笔记:值类型与引用类型(详解)
33C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(r1.x);   //显示5
34C#学习笔记:值类型与引用类型(详解)
35C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(v1.x);   //显示5
36C#学习笔记:值类型与引用类型(详解)
37C#学习笔记:值类型与引用类型(详解) 
38C#学习笔记:值类型与引用类型(详解)
39C#学习笔记:值类型与引用类型(详解)
40C#学习笔记:值类型与引用类型(详解)        //以上代码为图的左边部分,以下代码为右边部分
41C#学习笔记:值类型与引用类型(详解)
42C#学习笔记:值类型与引用类型(详解) 
43C#学习笔记:值类型与引用类型(详解)
44C#学习笔记:值类型与引用类型(详解)
45C#学习笔记:值类型与引用类型(详解)        SomeRef r2 = r1;           //只复制引用()
46C#学习笔记:值类型与引用类型(详解)
47C#学习笔记:值类型与引用类型(详解)        SomeVal v2 = v1;           //在堆栈上分配并复制成员 
48C#学习笔记:值类型与引用类型(详解)
49C#学习笔记:值类型与引用类型(详解)        r1.x = 8;                  //修改r1.x和r2.x  
50C#学习笔记:值类型与引用类型(详解)        v1.x = 9;                  //只修改v1.x而不修改v2.x
51C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(r1.x);   //8        
52C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(r2.x);   //8        
53C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(v1.x);   //9
54C#学习笔记:值类型与引用类型(详解)        Console.WriteLine(v2.x);   //5
55C#学习笔记:值类型与引用类型(详解)
56C#学习笔记:值类型与引用类型(详解)    }

57C#学习笔记:值类型与引用类型(详解)
58C#学习笔记:值类型与引用类型(详解)


C#学习笔记:值类型与引用类型(详解)

事实上通过这个示例,大家已经可以很清晰的区分值类型与引用类型的一些区别了,尤其关于赋值的问题:值类型赋值是通过值的复制来实现的,修改新的变量的值对原变量没有影响,而引用类型的赋值实际上是赋予给对象的引用,修改任何一个的值实际上修改了其引用,所有指向这个引用的变量的值都会发生改变。

但有时候你会发现这样的问题:

string s1 = "hello";
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






 

转载于:https://www.cnblogs.com/Jason_z/archive/2009/10/13/1582346.html