在体验C#的锐利之前,关乎语言基本知识的掌握是必不可少的一环。由于C#基本语言很多源自C/C++,在这里对那些和C/C++类似的地方仅作简单介绍,我们将体验专注于那些区别于传统C/C++的关键的语言基础知识。
数据类型
C#语言的数据类型主要分为两类:值类型和引用类型。另外一种数据类型"指针"是为unsafe上下文编程专门设定的,其中unsafe上下文指对代码进行unsafe标示以满足利用指针对内存直接进行操作要求的C#非托管代码,这些代码将失去Microsoft.NET平台的垃圾收集等CLR性质,我们放在"COM互操作 非托管编程与异常处理"专题里阐述。值类型的变量本身包含他们的数据,而引用类型的变量包含的是指向包含数据的内存块的引用或者叫句柄。从下面这幅图中可以清晰地看出两者的差别:
引用类型带来的可能的问题便是当多个变量引用同样的内存块时,对任何一个引用变量的修改都会导致该对象的值的改变。null值表示引用类型没有对任何实际地址进行引用。
值类型可分为结构类型和枚举类型。结构类型包括简单类型和用户自定义结构类型。枚举类型和用户自定义结构类型我们将在"第九讲 结构,枚举,数组与字符串"专题里详细阐述。简单类型又可分为布尔类型和数值类型。C#语言中布尔类型严格与数值类型区分,只有true和false两种取值,不存在像C/C++里那样和其他类型之间的转换。数值类型包括整值,浮点和decimal三种类型。整值类型有sbyte,byte,short,ushort,int,uint,long,ulong,char共九种。除了char类型外,其他8种两两一组分别为有符号和无符号两种。浮点值有float和double两种。decimal主要用于金融,货币等对精度要求比较高的计算环境。下表是对这些简单类型的一个详细的描述:
引用类型共分四种类型:类,接口,数组,委派。类除了我们可以定义自己的类型外,又包括两个比较特殊的类型object和string。object是C#中所有类型(包括所有的值类型和引用类型)的继承的根类。string类型是一个密封类型(不能被继承),其实例表示Unicode字符串,它和数组类型我们将放在"第九讲 结构,枚举,数组与字符串"中详述。接口类型定义一个方法的合同,我们将在"第七讲 接口 继承与多态"中讲述。委派类型是一个指向静态或实例方法的签名,类似于C/C++中的函数指针,将在"第八讲 委派与事件"中讲述。实际上我们将从后面的专题中看到这些类型都是类的某种形式的包装。
每种数据类型都有对应的缺省值。数值类型的缺省值为0或0.0,其中char的缺省为'\x0000'。布尔类型的缺省值为false。枚举类型的缺省值为0。结构类型的缺省值是将它所有的值类型的域设置为对应值类型的缺省值,将其引用类型的域设置为null。所有引用类型的缺省值为null。
不同类型的数据之间可以转换,C#的类型转换有隐含转换,明晰转换,标准转换,自定义转换共四种方式。隐含转换与明晰转换和C++里一样,数据从"小类型"到"大类型"的转换时为隐含转换,从"大类型"到"小类型"的转换为明晰转换,明晰转换需要如"(Type)data"一般的括号转换操作符。标准转换和自定义转换是针对系统内建转换和用户定义的转换而言的,两者都是对类或结构这样的自定义类型而言的。