你必须知道的.NET读书笔记分享——(4)值类型和引用类型

1、值类型和引用类型

    · 值类型实例分配在线程的堆栈上,并且不包含任何指向实例数据的指针,因为变量本身就包含了其实例数据;

  · 值类型实例总分配在它声明的地方,声明为局部变量时其被分配在堆栈上,声明为引用类型成员时其被分配到托管堆上。

  · 通常可以用Type.IsValueType来判断一个变量的类型是否为值类型;

  · .NET中以操作符ref和out来标识值类型按引用方式传递,其中区别是:ref在参数传递之前必须初始化,而out则在传递前不必初始化,且在传递时必须显示赋值;

  · sizeOf()运算符用于获取值类型的大小,但是不适用于引用类型。

  · Equals——System.ValueType重载了System.Object的Equals方法,用于实现对实例数据的判等;

  引用类型实例被分配在托管堆上,变量保存实例数据的内存引用。

  · 引用类型在性能上比如值类型。原因主要是引用类型变量要分配于托管堆上,内存释放由GC完成,造成一定的GC堆压力,同时必须完成对其附加成员的内存分配过程,以及对象访问问题。

  · ReferenceEquals只适用于引用类型,比较两个实例对象是否指向同一引用地址,对值类型应用ReferenceEquals将永远返回false;

  

2、值类型和引用类型的比较

    · 值类型都继承自System.ValueType,引用类型继承自System.Object;

  · 值类型是密封的,因此不能作为其他任何类型的基类,但是可以单继承或者多继承接口,而引用类型具有继承性;

  · 值类型不具有多态性,而引用类型具有;

  · 值类型会自动初始化为0,引用类型在默认情况下为null,表明没有任何指向托管堆的引用地址。

3、值类型和引用类型的适用场合

  

  值类型的适用场合:

  · 结构简单,数据较小;

  · 以存储数据为主要目的,而不是行为表现;

  · 没有子类继承的必要。

  引用类型的适用场合:

  · 结构复杂

  · 有继承、多态、突出行为

 

4、值类型和引用类型参数传递

  · 值类型传递的是实例拷贝,而引用类型传递的是引用地址拷贝;

  · 值类型按引用传递方式,实现的是对值类型参数实例的直接操作,方法调用方为该实例分配内存,而被调用方法操作该内存,也就是值类型的地址;而引用类型参数的按值传递方式,实现的是对引用类型的“值”引用指针的操作;

5、类型转换

   · 隐式转换:由低级类型向高级类型的转换过程。包括值类型的隐式转换(主要指数值类型等基本类型的隐式转换)、引用类型的隐式转换(主要指派生类向基类的转换)和值类型与引用类型之间的隐式转换(主要指装箱与拆箱)。

  · 显示转换:强制类型转换,不能保证数据的完整性,可能引起一定的精度损失或者不可知的异常,如:int a = (int) (b+2.02);

  · 使用explicit或者implicit进行用户自定义类型转换,主要给用户提供自定义的类型转换实现方式,以实现更有目的的转换操作,格式为:

    static (explicit/implicit) operator funName(params)

6、类型转换规则

  · 任何类型都可以安全地转换为基类类型

  · 任何类型转换为其派生类型时必须进行显示转换

  · 使用GetType可以取得任何对象的精确类型

  · 基本类型可以使用Convert类实现类型转换

7、装箱与拆箱

  · 装箱是将值类型数据转换为无类型的引用对象,使得我们可以将值类型视为对象来处理,通常转换为System.Object或其实现的任何接口引用类型。

    详解:在托管堆中分配内存空间——将值类型的字段拷贝到新分配的内存中——将托管堆中的对象地址返回给新的引用类型。

  · 拆箱是将引用类型转换为值类型,通常伴随着从堆中复制对象实例的操作。

    详解:首先检查是否为null,如果是则抛出NullReferenceException异常,不是则检查对象实例,确保它是给定值类型的装箱值,并且保证拆箱后的类型与原来是同一类型,否则抛出InvalidCastException异常。

  

注意:

1 static void Main(string[] args)
2 {
3 float f = 1.01f;
4 object o = f;
5 double d = (double)o; //将未装箱的引用类型强制转换为值类型,将抛出
                      InvalidCastException异常
6   Console.Read();
7 }

 

 

特殊的值类型和引用类型

 

1、字符串类型

  字符串具有恒定性,即字符串一经创建,就不可改变:

1 static void Main(string[] args)
2 {
3 string s = "test";
4 Console.WriteLine(s.Insert(0," Hi ".Substring(1).ToUpper())); //HI test
5   Console.WriteLine(s);//test
6   Console.Read();
7 }

   

1 static void Main(string[] args)
2 {
3 string a = "abcd";
4 string b = "abcd";
5 Console.WriteLine(ReferenceEquals(a,b)); //true
6   string c = "ab";
7 string d = c + "cd";//动态生成的字符串没有添加到CLR内部维护的哈希表
                    //使字符串驻留机制失效
8   Console.WriteLine(ReferenceEquals(a, d)); //false
9   d = string.Intern(d);//手动启用字符串驻留机制
10   Console.WriteLine(ReferenceEquals(a, d)); //true
11   string e = "ab" + "cd";//
12   Console.WriteLine(ReferenceEquals(a, e)); //true
13   Console.Read();
14 }

  · 字符串驻留是进程级的,可以跨应用程序域而存在,垃圾回收不能释放哈希表中引用的字符串对象,只有进程结束这些对象才会被释放·

2、枚举类型

  · System.Enum类型继承自System.ValueType,而ValueType是一切值类型的基类,但是System.Enum却是引用类型(而且是抽象类),这是System.ValueTye的唯一特例

  · 枚举类型是值类型,分配与线程的堆栈上,自动继承于Enum类型,但本身不能被继承;Enum是引用类型,分配于托管堆上,Enum类型本身不是枚举类型,但是提供了操作枚举类型的共用方法

  · 枚举定义时可以指明其基础类型(除char外的8种:byte、sbyte、short、ushort、int、uint、long和ulong)

  · 任意两个枚举常量不能具有同样的名称符号,但是可以具有相同的关联值

  · 枚举成员使用new初始化时,会关联值为0的枚举值,若没有0值常数,则weekend默认设定为0,如:

  

1 enum WithZero : int
2 {
3 a = 1,
4 b = 0
5 }
6 enum WithNonZero
7 {
8 a = 1,
9 b
10 }
11 static void Main(string[] args)
12 {
13 WithZero z = new WithZero();
14 WithNonZero nz = new WithNonZero();
15 Console.WriteLine(z);//b
16   Console.WriteLine(nz);//0
17   Console.Read();
18 }

      

1 enum Week : int
2 {
3 Sun = 7,
4 Mon = 1,
5 Tue,
6 Wed,
7 Thur,
8 Fri,
9 Sat,
10 Weekend = Sun
11 }
12 /// <summary>
13 /// 获取枚举中的符号名称和所有符号的数组
14 /// </summary>
15 static void Main(string[] args)
16 {
17 foreach (string item in Enum.GetNames(typeof(Week)))
18 {
19 Console.WriteLine(item);
20 }
21 foreach (Week item in Enum.GetValues(typeof(Week)))
22 {
23 Console.WriteLine("{0}:{1}", item.ToString("D"), item.ToString());
24 }
25 Console.Read();
26 }

作者:Rocky翔
出处:http://www.cnblogs.com/RockyMyx/
本文版权归作者和博客园共有,欢迎转载,但请在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2010-10-18 12:31  RockyXiang  阅读(252)  评论(0编辑  收藏  举报