ASP.NET程序设计教程(第2版)
上QQ阅读APP看书,第一时间看更新

3.2 C#语言的数据类型

C#有15种数据类型,这15种数据类型分为两大类:值类型和引用类型。值类型可以简单地理解为基本的数据类型,引用类型可理解为延伸的数据类型。值类型和引用类型的区别在于:值类型的变量直接存放实际的数据,而引用类型的变量存放的是数据的地址,即对象的引用。更通俗地说,值类型存放的是数据本身,而引用类型存放的是数据所处的位置说明。

3.2.1 值类型

值类型包括简单值类型和复合类型。简单值类型可以再细分为整数类型、字符类型、实数类型和布尔类型;复合类型则是简单类型的复合,包括结构(struct)类型和枚举(enum)类型。

1.整数类型

整数类型是最基本的数据类型,C#中共有8种整数类型,它们的区别在于表示数的范围、所占的存储空间的大小以及是否有符号位。8种整数类型如表3-2所示。

表3-2 整数类型

2.字符类型

字符(char)类型对应于.NET类库中的System.Char结构。C#中采用Unicode字符集来表示字符类型,所以单个汉字也可作为字符。例如:

一个Unicode的标准字符长度是16位,所以char类型在计算机中占两个字节。严格来说,字符类型也是一种特殊的整数类型,其取值范围与Unshort相同。C#与C语言不同的是,不能把整数直接赋值给char类型的变量,只能显式地将整数转换为char类型再赋值给char类型的变量。例如C语言中:

但是在C#中这是不允许的,即不允许从其他类型到char类型的隐式转换,必须进行显式转换,例如:

同C/C++一样,C#中也存在一些特殊字符,通过“\”加其他字符表示这些特殊字符,称为转义符。C#中的转义字符如表3-3所示。

表3-3 转义字符

3.实数类型

实数类型分为浮点类型float、double和小数类型decimal三种类型。它们的区别主要在于取值范围和精度的不同。其中,double类型的取值范围最广,decimal类型的精度最高。实数类型如表3-4所示。

表3-4 实数类型

虽然decimal类型精确度较高,但是取值范围较小。因此,从浮点类型向小数类型转换可能产生溢出异常,反之,可能出现精度损失。所以浮点类型和小数类型之间不存在隐式转换,必须使用强制类型转换。

注:decimal类型主要用于金融货币方面的计算。在直接书写decimal类型的变量时,必须在数值后面添加m或M,例如,decimal num=1.24m,否则编译会出错。

4.布尔(bool)类型

bool类型对应于.NET类库中的System.Boolean结构。它在计算机中占4个字节,即32位存储空间。C#与C语言在布尔类型的取值上完全不同。C语言用值“0”表示假,而任何非零值均取值“1”。而C#中布尔类型取值只能是true或者false。bool类型的变量不能与其他类型的变量相互转换。

5.结构类型

编程过程中经常会遇到需要将一系列不同数据类型的信息放在一起的情况,例如,学生表里包含学号、年龄和家庭住址等,这个时候就需要一种新的类型——结构类型,它可以把这些不同数据类型的信息组织成一个整体。结构中的数据类型没有限制,可以是简单值类型,也可以是结构类型或者是枚举类型。结构类型采用struct关键字来进行声明。

【操作实例3-2】 编写一个简单的结构体嵌套代码,代码如表3-5所示。

表3-5 结构类型举例

6.枚举类型

枚举实际上是为一组逻辑上密不可分的整数值创建一系列的别名。使用关键字enum来定义。

【操作实例3-3】 定义枚举Weekday,其内容为一周七天的英文名称,代码如表3-6所示。

表3-6 枚举类型举例

枚举类型要求其成员只能是整数类型。默认地,枚举中的每个元素的类型都是int型,且第一个元素的值为0,它后面的每一个元素的值依次加1。例如,表3-6中的程序,Sunday=0,Wednesday=3。也可以给枚举中的元素直接赋值,如把Sunday的值设为1,Monday的值设为3,其后元素的值分别为4,5……依次递增。枚举类型的变量在某一时刻只能取枚举类型中的某个元素。例如,表3-6定义的枚举变量w1,它的值要么是Sunday,要么是其他的星期元素,在同一时刻只能取一个值,且该值只能是枚举类型中的元素。

每个枚举类型都有一个基础类型,其基础类型可以是除char以外的任何整型,默认的基础类型为int,定义枚举类型时,可选择基础类型。定义基础类型的格式如下。

enum枚举类型名[:基类型]{由逗号分隔的枚举类型标示符}

注意,枚举类型中元素的值不能超过基础类型的取值范围。

例如,表3-7代码就是错误的。

表3-7 定义枚举基础类型错误代码

3.2.2 引用类型

引用类型变量不直接存储所包含的值,而是存储值的地址。引用类型包括类(class)、接口(interface)、代理(delegate)和数组(array)四种类型。

1.类(class)

类是一组具有相同数据结构和相同操作的对象集合。创建类的实例必须使用关键字new来进行声明。类和结构之间的根本区别在于:结构是值类型,而类是引用类型。对于值类型,每个变量直接包含自身的所有数据,每创建一个变量,就在内存中开辟一块区域;而对于引用类型,每个变量只存储对目标存储数据的引用,每创建一个变量,就增加一个指向目标数据的指针。C#中最常用的类有object和string两个。下面给出一个简单的类的实例。值得说明的是,“类”是面向对象编程中非常重要的概念,也是C#语言编程的重要基础。在本章后面的内容中,将有专门的篇幅重点说明“类”的概念。

【操作实例3-4】 编写一个简单的类,程序代码如表3-8所示。

表3-8 类的定义举例

2.接口(interface)

应用程序之间要相互调用,就必须事先达成一个协议,被调用的一方在协议中对自己所能提供的服务进行描述。在C#中,这个协议就是接口。接口定义中对方法的声明,既不包括访问限制修饰符,也不包括方法的执行代码。如果某个类继承了一个接口,那么它就要实现该接口所定义的服务,也就是实现接口中的方法。其定义如表3-9所示。

【操作实例3-5】 编写一个简单的接口。

表3-9 接口的定义举例

3.代理(或委托)(delegate)

代理即指代,就是定义一种变量来指代一个函数或者一个方法,其使用过程分为以下三个步骤。

1)定义:delegate void MyDelegate();

2)实例化:MyDelegate hd=new MyDelegate(p1.Say);

3)调用:hd();

4.数组(array)

C#语言中的数组与C语言中数组的概念和用法相同。主要用于同一数据类型的数据进行批量处理。与C语言相同,C#的数组也要初始化之后才能使用。数组的具体使用方法见3.4节。

3.2.3 装箱和拆箱

C#语言编程时经常需要将值类型和引用类型进行相互转换。在C#中这种转换操作用装箱和拆箱来实现。

装箱就是将值类型转换为对象类型,其本质就是创建一个对象,并将值赋给该对象。拆箱就是将对象类型转换为值类型,即将值从对象中复制出来,装箱与拆箱实例如表3-10所示。

表3-10 装箱与拆箱实例