初识.NET的公共类型系统CTS

目录
1. 公共类型系统简介
2. 值类型和引用类型
3. Boxing(装箱)和UnBoxing(拆箱)
4. 小结

1.公共类型系统简介
时至今日,编程语言已经发展的丰富多彩,但是他们几乎都有类似的特点—支持各种数据类型(如整形、字符串形等),代码模块化及面向对象。.NET平台利用了不同语言的这个相近的共性,抽象出公共类型系统CTS(Common Type System)。公共类型系统构成了.NET框架的公共语言运行时的基础,其中最重要的一个体现就是.NET平台的多语言支持,而运行于.NET平台的每一种语言又为了维护自己的语法特色,便使用别名来代替.NET的基础数据类型,如Visual Basic .NET中的Integer类型以及C#中的int类型实际上是基础数据类型System.Int32的化名。
公共类型系统不仅定义了所有的数据类型,并提供了面向对象的模型以及各种语言需要遵守的标准。CTS可以分为两个大类:值类型和引用类型,同时这两种类型之间还可以进行强制转换,这种转换被称为Boxing(装箱)和UnBoxing(拆箱)。从图表1可以看出公共类型系统的基本结构,CTS的每一种类型都是对象,并继承自一个基类—System.Object。

图表1. 公共类型系统CTS的体系

2. 值类型和引用类型
值类型是继承自ValueType类,值类型的变量直接存储数据,实例是被分配在栈中的,并且永远不可能为空。通过下面的例子可以看出,两个整形变量是分别存储数据的,如下面的代码,无论哪个变化都不会影响另一个。
[C#] 
Int16 iA 
= 123
Int16 iB 
= iA; 
iA 
= 321
Console.WriteLine(
"A = {0}", iA);
 Console.WriteLine("B = {0}", iB);
引用类型是继承自Object,引用类型变量存储的是数据内存的地址,而实例是被分配在可以进行垃圾回收的堆中的。一份数据可以被多个变量引用,使用这种变量类型能够起到节省内存资源的作用,同时也会由于一个引用变量的修改而导致其他引用的变更。引用类型的变量是可以为空的,那表示它不指向任何对象。如下面的代码,可以看出clsA和clsB实际上都指向内存中同一个对象的实例。
[C#] using System; 
class Class1 static void Main(string[] args) 
    clsRef clsA 
= new clsRef(); 
    clsA.iValue 
= 123
    clsRef clsB 
= clsA; 
    clsB.iValue 
= 321
    Console.WriteLine(
"A = {0}", clsA.iValue); 
    Console.WriteLine(
"B = {0}", clsB.iValue); 
    Console.Read(); 
}
 
class clsRef 

    
public Int16 iValue; 
}

3. Boxing(装箱)和UnBoxing(拆箱)
将值类型数据指定给引用类型数据时,系统会先从堆之中配置一块内存,然后将值类型数据复制到这一内存,最后再使引用类型数据指向到这一内存,这样的过程称为Boxing(装箱)。
 装箱可以是显式的,也可以是隐式的。
[C#] Int16 I = 123; object objRef = I; 
反之即为UnBoxing(拆箱),而且只有引用类型数据需要拆箱。
[C#] Int16 J; J = (Int16)objRef; 
在装箱的过程中,内存的配置是很费时的操作,虽然透明于程序员,考虑到程序的执行效能,我们应该尽量避免不必要的装箱操作。
 
有两种方式来查看包装以后的引用对象中包装的原始数据的类型。要判断原始类型是否是某个给定的原子类型,用is;如果要返回一个字符串,可以用object类的GetType方法。
int i = 10;
object obj = i; //隐式装箱
object obj = object(i); //显式装箱
if(obj is int//int
       Console.WriteLine(“OK”);
Console.WriteLine(obj.GetType()); 
//System.Int32

4. 小结
公共类型系统还包括Classes,Delegates,Arrays,Interfaces和Pointers等类型,提供了面向对象、事件及回调函数处理、数组和接口等功能。总之CTS是通向.NET的必经之路,打下良好的基础便能灵活运用.NET中的各种数据类型,做到以不变应万变。