第1章 C#入门基础

Download Report

Transcript 第1章 C#入门基础

第1章
C#入门基础
Microsoft公司是这样描述C#的:“C#是从C和C++派生来
的一种简单、现代、面向对象和类型安全的编程语言。
C#(读做'Csharp')主要是从C/C++编程语言家族移植过
来的,C和C++的程序员会马上熟悉它。C#试图结合
Visual Basic的快速开发能力和C++的强大灵活的能力。
”。本章将讲解使用C#语言开发的入门知识,主要介绍
以下知识点。
 .NET Framewrok;
 搭建Visual Studio 2008开发环境;
 创建第一个控制台应用程序;
 创建第一个Windows窗体应用程序。
C#从入门到实践
1.1
C#概述
C#是一种简单的、现代的、面向对象的、类型安全的编程
语言。它不但提供了面向对象编程的技术,而且还提供
了面向组件编程的支持技术。Visual C# 2008提供了许多
方便开发的工具,如高级代码编辑器、方便的用户界面
设计器、集成调试器等。开发人员使用这些工具,可以
更容易在C#语言3.0版和.NET Framework 3.5版的基础上
开发应用程序。(源码网整理:www.codepub.com)
C#从入门到实践
1.1.1
C#语言
C#是一种Microsoft公司设计的、简洁的、类型安全的、面
向对象的语言,它松散地基于C/C++语言,并且有很多方
面和Java语言类似。开发人员可以使用C#语言来构建在
.NET Framework上运行的各种安全、可靠的应用程序。
C#语法表现力强、简单易学、容易上手。通常地,开发人
员通过很短的时间的学习,就能够使用C#语言开发高效
的程序。C#语法提供了许多强大的功能,如可为空置(
null)的值类型、枚举、委托、lambda表达式、直接内存
访问等。C#支持泛型类型和方法,进而提供了更为出色
的类型安全和性能。特别地,C#还提供了迭代器、语言
集成查询(LINQ)表达式等高级功能,使得开发人员可
以在C#代码中创建具有查询功能的程序代码。
C#从入门到实践
1.1.2
.NET框架
C#程序必须在.NET Framework上运行。.NET Framework是
Windows的一个不可或缺的组件,是一个支持构建、部署和运
行下一代应用程序和Web服务的完整Windows组件。.NET
Framework能够提供效率极高的、基于标准的多语言(如C#、
VB.NET、C++、J#等)环境,能够将现有的应用程序与下一
代应用程序和服务集成,并能迅速部署和操作Internet规模的
应用程序。.NET Framework主要包括两个组件:公共语言运
行库(Common Language Runtime,简称为CLR)和.NET
Framework类库(Class Library)。
1.公共语言运行库
2..NET Framework类库
3.公共语言运行库、.NET Framework类库和应用程序的关系
4.语言互操作性
5.C#应用程序执行流程
C#从入门到实践
1.1.3
C#应用程序
C#应用程序包括两种应用程序:控制台(Console)应用程
序(1.3小节创建的应用程序就是一个控制台应用程序)
和Windows窗体应用程序(1.4小节创建的应用程序就是
一个Windows窗体应用程序)。控制台应用程序的界面
往往比较简单,而Windows窗体应用程序能够提供丰富
的图形界面。
1.控制台应用程序
2.Windows窗体应用程序
C#从入门到实践
1.2
搭建Visual Studio 2008开发环境
本小节介绍搭建开发C#应用程序(如Windows窗体应用程
序、ASP.NET网站等)的环境,包括安装Microsoft
Visual Studio 2008、配置集成开发环境(IDE)、熟悉集
成开发环境(IDE)等内容。
注意:笔者机器的操作系统为Microsoft Windows Server
2003 Enterprise Edition Service Park 2。
C#从入门到实践
1.2.1
安装Microsoft Visual Studio 2008
下面介绍在笔者机器上安装Microsoft Visual Studio Team
System 2008简体中文版的操作步骤,具体如下。
C#从入门到实践
1.2.2
配置集成开发环境(IDE)
由于Microsoft Visual Studio 2008集成开发环境(IDE)非常
复杂,为了以后能够更加方便地开发各种C#应用程序,
在此,特意详细介绍配置Microsoft Visual Studio 2008集
成开发环境的方法。
C#从入门到实践
1.2.3
熟悉集成开发环境(IDE)
Microsoft Visual Studio 2008集成开发环境包括多个可以停
靠或浮动的面板,如“工具箱”、“服务器资源管理器
”、“解决方案资源管理器”、“属性”等面板。
C#从入门到实践
1.3
创建第一个控制台应用程序
本节介绍使用Microsoft Visual Studio 2008集成开发环境(
IDE)创建第一个控制台应用程序——Sample_01_CA的
方法,以及开发Sample_01_CA应用程序所涉及的各种基
本技术,如编写C#代码、运行应用程序等。
C#从入门到实践
1.3.1
创建Sample_01_CA控制台应用程序
依次选择“开始”|“所有程序”|“Microsoft Visual Studio
2008”|“Microsoft Visual Studio 2008”命令,打开“起始
页 - Microsoft Visual Studio”对话框。单击“最近项目”
面板中的“创建”下的“项目”链接,弹出“新建项目
”对话框,如图1.24所示。
C#从入门到实践
1.3.2
解决方案资源管理器
创建Sample_01_CA控制台应用程序成功之后,Microsoft
Visual Studio 2008集成开发环境(IDE)将为该应用程序
创建一个默认类文件,名称为“Program.cs”。打开“解
决方案资源管理器”面板,可以查看Sample_01_CA控制
台应用程序包含的所有资源和数据,如图1.25所示。
C#从入门到实践
1.3.3
Program.cs文件
双击“解决方案资源管理器”面板中的“Program.cs”节点
,打开Program.cs文件。该文件为Sample_01_CA控制台
应用程序提供主入口点。
C#从入门到实践
1.3.4
AssemblyInfo.cs文件
首先展开“解决方案资源管理器”面板中的“Properties”节
点,然后双击“AssemblyInfo.cs”节点打开
AssemblyInfo.cs文件。该文件用来配置Sample_01_CA控
制台应用程序的程序集信息。
C#从入门到实践
1.3.5
运行应用程序
按下“F5”按钮或者单击Microsoft Visual Studio 2008集成开
发环境中的按钮即可运行Sample_01_CA控制台应用程序
。该应用程序运行之后,显示一个黑色的控制台对话框
,如图1.26所示。
C#从入门到实践
1.4
创建第一个Windows窗体应用程序
本节介绍使用Microsoft Visual Studio 2008集成开发环境(
IDE)创建第一个Windows窗体应用程序——
Sample_01_WFA的方法,以及开发Sample_01_WFA应
用程序所涉及的各种基本技术,如设计Windows窗体、
编写C#代码、配置应用程序、运行应用程序等。
C#从入门到实践
1.4.1
创建Sample_01_WFA Windows窗体应用
程序
依次选择“开始”|“所有程序”|“Microsoft Visual Studio
2008”|“Microsoft Visual Studio 2008”命令,打开“起始
页 - Microsoft Visual Studio”对话框。单击“最近项目”
面板中的“创建”下的“项目”链接,弹出“新建项目
”对话框,如图1.27所示。
C#从入门到实践
1.4.2
解决方案资源管理器
创建Sample_01_WFA Windows窗体应用程序成功之后,
Microsoft Visual Studio 2008集成开发环境(IDE)将为
该应用程序创建一个默认Windows窗体,名称为
“Form1.cs”。打开“解决方案资源管理器”面板,可以
查看Sample_01_WFA Windows窗体应用程序包含的所有
资源和数据,如图1.28所示。
C#从入门到实践
1.4.3
Form1.cs窗体
在“解决方案资源管理器”面板中双击“Form1.cs”节点,
打开Form1.cs窗体的设计界面,如图1.29所示。此时,开
发人员可以直接将“工具箱”面板中的控件拖放到
“Form1.cs”窗体上。
C#从入门到实践
1.4.4
Form1.Designer.cs文件
首先展开“解决方案资源管理器”面板中的“Form1.cs”节
点,然后双击“Form1.Designer.cs”节点打开
Form1.Designer.cs文件。该文件中的代码为Form1.cs窗体
的设计代码,用来描述Form1.cs窗体上的每一个控件。
C#从入门到实践
1.4.5
Form1.cs窗体的代码
右击“解决方案资源管理器”面板中的“Form1.cs”节点,
打开Form1.cs窗体的代码文件。该文件保存Form1.cs窗体
的事件等设计代码。
C#从入门到实践
1.4.6
Program.cs文件
双击“解决方案资源管理器”面板中的“Program.cs”节点
,打开Program.cs文件。该文件为Sample_01_WFA
Windows窗体应用程序提供主入口点。
C#从入门到实践
1.4.7
AssemblyInfo.cs文件
首先展开“解决方案资源管理器”面板中的“Properties”节
点,然后双击“AssemblyInfo.cs”节点打开
AssemblyInfo.cs文件。该文件用来配置Sample_01_WFA
Windows窗体应用程序的程序集信息。
C#从入门到实践
1.4.8
运行应用程序
按下“F5”按钮或者单击Microsoft Visual Studio 2008集成开
发环境中的“”按钮即可运行Sample_01_WFA Windows
窗体应用程序。该应用程序运行之后,显示的第一个对
话框为“Form1”对话框,如图1.30所示。
C#从入门到实践
1.5
小结
本章主要介绍了搭建开发Visual Studio 2008集成开发环境,
以及C#语言和.NET Framework的概述。其中,读者要着
重掌握使用Visual Studio 2008集成开发环境开发第一个
控制台应用程序和Windows窗体应用程序的方法。只有
这样,才能进行后续的开发。下一章将要介绍使用C#语
言如何编写第一个应用程序。
C#从入门到实践
1.6
习题
1.在本章介绍的Sample_01_WFA Windows窗体应用程序
之上,实现以下功能。
(1)添加名称为“Dialog.cs”的窗体到应用程序中。
(2)运行该应用程序。
C#从入门到实践
第2章
C#基本概念
C#语言从1.0版本发展到3.0版本经历了比较长的时间,现在
已经是一种比较完善、简单、易学的编程语言。为了读
者能够首先对C#语言有一个简单的认识,笔者特意在本
章介绍了Hello World应用程序和C#语言的一些常见的基
本概念,主要介绍以下知识点。
 创建Hello World应用程序;
 编译Hello World应用程序;
 运行Hello World应用程序;
 C#程序的概念扩展。
C#从入门到实践
2.1
创建Hello world应用程序
对于C#初学者而言,Hello world应用程序是C#语言入门最
好的、简单的示例程序。该程序可以在控制台中显示
“Hello world”字符串。下面介绍书写该程序的基本方法
。
C#从入门到实践
2.1.1
创建hello.txt文本文件
为了方便初学者真正认识C#程序,我们这里不使用集成开
发环境来编写本程序,而是使用记事本来编写程序。新
建一个名称为“hello.txt”的文本文件,并打开该文件。
C#从入门到实践
2.1.2
创建HelloWorld类
任何一个C#应用程序都是由类(class)组成。一个C#应用
程序可以包括一个类或多个类。类实际上是对某种类型
的对象定义变量和方法的原型。它表示对现实生活中一
类具有共同特征的事物的抽象,是面向对象程序设计(
Object-Oriented Programming,简称为OOP)的基础。
面向对象程序设计指一种程序设计范型,它将对象作为程序
的基本单元。在面向对象程序设计中,最为基本的概念
是类(class)和对象(object),对象又称为实例。
1.类
2.对象
C#从入门到实践
2.1.3
添加Main()方法
一旦创建一个类之后,但是不为该类添加任何成员,那么该
类就是一个空类,即它不能描述世界上的任何一种对象
。为了使得类能够描述一种对象,那么就需要为该类添
加一些属性和行为。
一个行为就产生一个动作。在类中,使用方法(method)
来描述这一行为。也就是说,方法是一个类能做的事情
(即一些计算或操作),但是并没有做这事情。作为一
条狗而言,它是会吠叫、会坐下、会吃。因此,为了能
够使用Dog类描述狗,那么就需要在该类中定义以下3个
方法。
 Bark(),吠叫。
 Sit(),坐下。
 Eat(),吃。
C#从入门到实践
2.1.4
调用WriteLine()方法
在Dog类中,虽然定义了狗的3个行为:吠叫、坐下和吃,
但是并没有使这3个行为发生。如果想要芊芊这一条狗吠
叫,那么就需要一个主动的动作使得芊芊吠叫。这一个
主动的动作就是调用该行为对应的方法,即通过调用方
法使得该方法对应的行为发生。
C#从入门到实践
2.1.5
引入System命名空间
世界上存在很多狗,而且一些狗的名字也相同。譬如,张三
家的狗叫芊芊,而李四家的狗也叫芊芊。那么如何区分
这两家的狗呢?自然,称呼张三家的狗可能是“张三家
的芊芊”,称呼李四家的狗可能是“李四家的芊芊”。
通过这种方式,就能够区分张三家和李四家的芊芊了。
C#从入门到实践
2.1.6
整理Hello world应用程序的代码
经过上述步骤之后,就已经书写了一个完整的C#应用程序
——Hello world应用程序,它的完整的程序代码如下。
using System;
class HelloWorld
{
static void Main()
{
Console.WriteLine("Hello, World");
}
}
C#从入门到实践
2.2
编译和运行Hello World应用程序
2.1小节仅仅书写了Hello world应用程序的代码。如果要将
这一段程序代码成为一个可以执行的文件,则需要使用
Microsoft C#编译器编译这一段代码。
(源码网整理:www.codepub.com)
C#从入门到实践
2.3
C#程序的概念扩展
在2.1小节中介绍了C#面向对象程序设计的一些基本概念,
如类、对象、实例、属性、方法、调用方法等。除了上
述这些概念之外,还有一些比较常用的概念,如继承性
、多态性等。
1.继承性
2.多态性
3.接口
C#从入门到实践
2.4
小结
本章主要介绍了“Hello world”应用程序,包括创建Hello
World应用程序、编译Hello World应用程序、运行Hello
World应用程序和分析Hello World应用程序。其中,读
者需要着重掌握使用记事本创建Hello World应用程序的
方法。下一章将介绍C#的类型。
C#从入门到实践
2.5
习题
使用记事本撰写一个名称为“Test_02”的C#应用程序的代码
,并将此代码编译为一个名称为“Test_02.exe”的可执行
文件。Test_02应用程序在控制台显示“This is a C#
program.”字符串。
C#从入门到实践
第3章
类型
类型是C#语言中最为基本的概念之一。不同类型的变量将
拥有不同的数据存储方式和操作方法。C#语言的类型系
统是统一的,它可以把任何类型的值都按照对象来处理
。本章将讲解C#语言中各种类型,主要介绍以下知识点
 值类型;
 引用类型;
 装箱;
 拆箱。
C#从入门到实践
3.1
类型概述
C#语言中的每一个类型都直接或间接派生于object类型,即
object类型是C#语言所有类型的最终基类型。C#语言的
类型可以分为以下3种类型。
 值类型(value-type),它的变量直接包含其数据。
 引用类型(reference-type),它的变量只存储对其数据
的引用(即访问其数据的访问地址)。引用类型的变量
又称为对象(object)。
 指针类型(point-type),和C、C++语言中的指针类似
,而且只能用作在不安全代码中。由于在C#编程中很少
使用指针类型,因此,在此不做详细介绍。
C#从入门到实践
3.2
值类型
值类型要么是结构类型,要么是枚举类型。值类型的变量直
接包含其数据,而且其值不可能为null。在操作值类型的
变量时,只会影响该变量的数据,而不会影响另外一个
变量的值。所有的值类型都直接或间接派生于
System.ValueType类型。
值类型包括结构类型、枚举类型、布尔类型、自定义结构类
型、sbyte、byte、char、short、ushort、int、uint、long
、ulong、float、double和decimal类型。其中,C#语言提
供了一种被称为“简单类型(simple type)”的预定义结
构类型。这些类型通过C#保留字标识,如char、int等。
本节将详细介绍值类型的知识点。
C#从入门到实践
3.2.1
System.ValueType类型
所有值类型都直接或间接从System.ValueType类隐式继承而
来,并且任何类型不能从值类型派生而来。
System.ValueType本身是一个类,它只包含以下3个方法
。
 Equals(),判定当前实例与指定的对象是否相等。
 GetHashCode(),返回当前实例的哈希代码。该哈希代码
用于哈希表(一种数据结构)的散列运算。
 ToString(),返回当前实例的完全限定类型名称。
C#从入门到实践
3.2.2
整数类型
整数类型包括9种类型,如sbyte、byte、short等。它们的具体说明
、.NET Framework中的名称和取值范围如表3.1所示。
1.int类型
2.long类型
3.char类型
类型
描述
.NET Framework中的名称
取值范围
sbyte
有符号8位整数
System.SByte
-128~127
byte
无符号8位整数
System.Byte
0~255
short
有符号16位整数
System.Int16
-32768~32767
ushort
无符号16位整数
System.UInt16
0!65535
int
有符号32位整数
System.Int32
-2147483648~2147483647
uint
无符号32位整数
System.UInt32
0~4294967295
long
有符号64位整数
System.Int64
-9223372036854775808~9223372036854775807
ulong
无符号64位整数
System.UInt64
0~18446744073709551615
char
无符号16位整数
System.Char
0~65535,16位的Unicode字符。
C#从入门到实践
3.2.3
浮点型
C#语言包括两种浮点型:float和double。float类型表示32位
的单精度浮点数,它的取值范围为±1.5e-45~±3.4e38。
double类型表示64位的双精度浮点数,它的取值范围为
±5.0e-324~±1.7e308。浮点数包括以下3种特殊的值。
 正零和负零
 正无穷大和负无穷大
 非数字(Not-a-Number)值
C#从入门到实践
3.2.4
decimal类型
decimal类型表示128位的数值,取值范围为±1.0e28~±7.9e28,特别适用于财务计算和货币计算。和float
类型一样,在书写decimal类型的值时,需要在数值后添
加后缀m,否则编译出错。
与浮点型相比,decimal类型具有较高的精度,但取值范围
较小。因此,从浮点型到decimal类型的转换可能会产生
溢出异常,而从decimal类型到浮点型的转换则可能导致
精度损失。正是由于这些原因,所以,在浮点型和
decimal类型之间不存在隐式转换。如果要转换浮点型到
decimal类型,则必须使用强制转换方法。
C#从入门到实践
3.2.5
bool类型
bool类型表示布尔逻辑量。它只包含两个值:true和false,
而且这两个值意义恰好相反。
C#从入门到实践
3.2.6
枚举类型
枚举(enum)类型也是一种值类型,它具有命名常量的独
特的类型。每个枚举类型都有一个基础类型,该基础类
型必须为byte、sbyte、short、ushort、int、uint、long或
ulong。其中,默认的基础类型为int。
枚举类型一般包含一个或多个枚举值,每一个枚举值之间用
逗号(,)分隔。枚举值又称为枚举数,它的默认基础类
型为int。默认情况下,第一个枚举数的值为0,后面的每
一个枚举数的值依次增1。
C#从入门到实践
3.2.7
结构类型
结构类型也是一种值类型,它可以声明常量、字段、方法、
属性、索引器、运算符、实例构造函数、静态构造函数
和嵌套类型。有关结构类型的知识点将在第9章中进行详
细介绍。
C#从入门到实践
3.2.8
实例一:把整数转换为二进制数
【实例3-1】实现把整数转换为二进制数的功能。该功能由
ConvertIntToBinary(int n)静态函数实现,n参数表示被
转换的整数,该函数返回二进制数的字符串形式。
C#从入门到实践
3.2.9
实例二:把二进制数转换为整数
【实例3-2】实现把二进制数转换为整数的功能。该功能由
ConvertBinaryToInt(string binary)静态函数实现,binary
参数表示被转换的二进制数的字符串形式,该函数返回
一个整数。
C#从入门到实践
3.3
引用类型
引用类型主要包括6种类型:object类型、string类型、类类
型、数组类型、接口类型和委托类型。引用类型变量的
值是对该类型的某个实例的一个引用。其中,类型的实
例被称为对象。在引用类型中,存在一个很特殊的值:
null。null能够兼容所有的引用类型,表示“每一被引用
的实例”。本节将详细介绍引用类型的知识点。
C#从入门到实践
3.3.1
对象类型
对象(object)类型是C#类型系统中所有其他类型的最终基
类。C#中的每种类型都是直接或间接从object类类型派生
的。因此,C#中的任何类型都可以转换为object类型。
C#从入门到实践
3.3.2
字符串类型
字符串(string)类型是直接从object继承而来的类类型,它
对应着.NET Framework中的System.String类型。
C#从入门到实践
3.3.3
类类型
类(class)类型是C#中最常用的类型。它是一个数据结构
,能够定义数据成员、函数成员和嵌套类型等内容。其
中,数据成员包括常量和字段,函数成员包括方法、属
性、事件、索引器、运算符、实例构造函数、析构函数
和静态构造函数。
特别地,类类型还支持一种被称为“继承”的机制。继承是
指派生类可用来扩展和专门化基类的一种机制。有关类
类型的知识点将在第8章中进行详细介绍。
C#从入门到实践
3.3.4
数组类型
数组(Array)是一种数据结构,它可以将多个类型相同的
元素组合为一个整体,从而通过数组统一访问或操作这
些元素。数字可以通过计算索引来访问数组中的每一个
元素。每一个元素的类型称为数字的元素类型。
C#从入门到实践
3.3.5
接口类型
接口(interface)类型和类类型非常相似。它也是一个数据
结构,能够声明数据成员和函数成员。其中,数据成员
主要包括属性,函数成员包括方法和事件。
C#从入门到实践
3.3.6
委托类型
委托(delegate)也是一种数据结构,它能够引用一个或多
个方法。特别地,对于实例方法,它还能够引用这些方
法所对应的对象实例。读者如果熟悉C++中的函数指针,
那么就不难理解委托这一概念了。
委托类型类似于C++中的函数指针,但是它是类型安全的。
委托类型能够将方法作为参数进行传递,并且还可以定
义回调方法。
C#从入门到实践
3.4
装箱和拆箱
引用类型总是分配在托管堆上,而值类型总是分配在堆栈上
。有时,程序需要获取指向值类型的引用。此时,需要
将值类型转换为引用类型,这一操作被称为装箱。反之
,把引用类型转换为值类型称为拆箱。
装箱和拆箱是C#的类型系统中两个很重要的概念,它在值
类型和引用类型之间的架起了一座桥梁。通过装箱和拆
箱操作,可以将任何值类型的变量的值转换为引用类型
的变量的值。反之,也可以进行转换。特别地,有了装
箱和拆箱操作,就可以将C#类型系统中的任何类型的值
最终都可以按对象来处理。
C#从入门到实践
3.4.1
装箱
装箱是指将值类型隐式转换为引用类型。对于值类型而言,
装箱的具体操作为:首先分配一个对象实例,然后将值
类型的值复制到该实例中。装箱前后不是同一个实例。
对于引用类型而言,装箱前后都共享同一个实例。
C#从入门到实践
3.4.2
拆箱
拆箱是指将引用类型隐式转换为值类型。拆箱的具体操作包
括以下2个步骤。
(1)检查该对象实例是否为给定值类型的一个装了箱的值
。
(2)将值从实例中复制出来。
C#从入门到实践
3.5
小结
本章主要介绍了C#语言的类型系统的基础知识,如值类型
、引用类型、类型转换、装箱、拆箱等。其中,读者要
着重掌握值类型和引用类型,为后续编写C#程序代码奠
定基础。下一章将要介绍C#语言中的变量。
C#从入门到实践
3.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_03”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个整型变量vint和一个字符串变量vstring,将
vint变量转换为字符串,将vstring变量转换为一个整数。
C#从入门到实践
第4章
变量
变量是C#语言中最为基本的概念之一,它表示存储位置。
每一个变量的值由其类型确定。本章将讲解C#语言中各
种变量,主要介绍以下知识点。
 变量概述;
 变量分类;
 变量赋值;
 使用值参数传递数据;
 使用ref参数传递数据;
 使用out参数传递数据;
 变量转换。
C#从入门到实践
4.1
变量概述
在C#语言中,变量表示存储位置。每一个变量都具有一个
类型,该类型确定变量存储的内容。对于两个变量而言
,如果它们的值相同,但是类型不同,那么该变量存储
的值是不相同的。
声明一个变量之后,该变量可能具有初始值,也可能不具有
初始值。如果变量具有初始值,则称之为初始已赋值(
initially assigned)。如果变量不具有初始值,则称之为
初始未赋值(initially unassigned)。
如果是第一次明确指定变量的值,则称之为变量的初始化。
如果是初始未赋值变量,必须经过初始化之后,才能够
被使用。
C#从入门到实践
4.2
变量分类
C#语言定义了7种不同类别的变量:静态变量、实例变量、
数组元素、值参数、引用参数、输出参数和局部变量。
本小节将详细介绍这7种类别的变量。
C#从入门到实践
4.2.1
静态变量
静态变量(static variable)是指使用static修饰符声明的变
量。静态变量总是在包含了它的那个类型的静态构造函
数(第8章)执行之前就存在了,在关联的应用程序域终
止时终止。
C#从入门到实践
4.2.2
实例变量
实例变量(instance variable)和静态变量相对应。实例变
量是指未使用static修饰符声明的变量。实例变量包括两
种类型的变量:类的实例变量和结构的实例变量。
1.类的实例变量
2.结构的实例变量
C#从入门到实践
4.2.3
局部变量
顾名思义,局部变量(local variable)是在应用程序的某一
段时间内存在。局部变量可以声明在块(block)、for语
句、switch语句和using语句中,即局部变量是通过
“local-variable-declaration”来声明的。
C#从入门到实践
4.2.4
值参数
对于一个函数成员而言,它都存在一个参数列表(紧跟在函
数成员名称之后的小括弧中)。当然,该参数列表可以
是空,也可以包含一个或多个参数,多个参数之间使用
逗号(,)分隔。
在声明参数时,可以不使用修饰符,也可以使用ref或out修
饰符。值参数(value parameter)是指未使用ref或out修
饰符声明的参数。
C#从入门到实践
4.2.5
ref参数
引用参数(reference parameter)是值使用ref修饰符声明的
参数。引用参数和值参数最大的一个区别在于:在函数
成员中,函数成员为值参数分配了一个新的存储位置,
而引用参数仍然使用其基础变量的存储位置。即引用参
数和其基础变量操作了同一个变量,而值参数和其基础
变量是操作了两个不同变量,而且不互相影响。
C#从入门到实践
4.2.6
out参数
输出参数(output parameter)是值使用out修饰符声明的参
数。输出参数和值参数最大的一个区别在于:在函数成
员中,函数成员为值参数分配了一个新的存储位置;输
出参数不创建新的存储位置,而是使用基础变量的存储
位置。因此,输出参数的值总是与基础变量相同。
简而言之,基础变量实际上是分配了一个存储位置,在调用
包含out参数的函数成员时,该函数成员将在这一个存储
位置存储新的值,并修改基础变量的值。
C#从入门到实践
4.2.7
数组元素
数组元素是指作为函数成员参数的数组(第8章)的元素,
它总是在创建数组实例时开始存在,在没有对该数组实
例的引用时停止存在。每个数组元素的初始值都是其数
组元素类型的默认值。
C#从入门到实践
4.3
变量赋值
变量赋值是指给变量指定某一个明确的值,如“int i =
2008;”语句在声明i变量的同时给该变量赋值为2008。在
函数成员可执行代码中的给定位置,如果编译器可确定
变量已自动初始化或已成为至少一个赋值的目标,则称
该变量已明确赋值(definitely assigned)。
C#从入门到实践
4.4
实例一:使用值参数传递数据
【实例4-1】演示了使用值参数传递数据的方法。该功能由
static int CountSum(int i,int j)静态函数实现,i和j参数均
为值参数。CountSum(int i,int j)函数返回i和j参数的值增
1之后的和。
C#从入门到实践
4.5
实例二:使用ref参数传递数据
【实例4-2】演示了使用ref参数传递数据的方法。该功能由
static int RefCountSum(ref int i,ref int j)静态函数实现,i
和j参数均为ref参数。RefCountSum(ref int i,ref int j)函
数返回i和j参数的值增1之后的和。
C#从入门到实践
4.6
实例三:使用out参数返回数据
【实例4-3】演示了使用out参数传递数据的方法。该功能由
static void OutCountSum(int i,int j,out int sum)静态函数
实现,i和j参数均为的值参数,sum参数为out参数。
OutCountSum(int i,int j,out int sum)函数本身不返回值,
但是用sum参数保存i和j参数的值增1之后的和。
C#从入门到实践
4.7
变量转换
转换(conversion)使一种类型的表达式可以被视为另一种
类型。变量转换(variable conversion)使一种类型的变
量可以被视为另一种类型。转换可以分为隐式转换(
implicit conversion)和显式转换(explicit conversion)
。如果在转换时,需要添加强制转换的类型,那么该转
换为显式转换。本小节将介绍变量转换的知识点。
C#从入门到实践
4.7.1
隐式转换
隐式转换是指不需要添加强制转换的类型的转换。常用的隐
式转换包括以下几种。
 标识转换,在同一类型内进行转换,它能够使已具有所
需类型的实体可被认为是可转换的。
 隐式数值转换,如从int类型转换为long类型等。
 隐式枚举转换,将数值转换为枚举类型。
 隐式引用转换,如引用类型转换为object类型等。
 装箱转换,如值类型转换为object类型等。
 隐式常量表达式转换,如将int类型转换为uint类型等。
 用户定义的隐式转换,包括以下3个步骤:一个标准的隐
式转换;执行用户定义的隐式转换运算符;另一个标准
的隐式转换。
C#从入门到实践
4.7.2
显示转换
显式转换是指需要添加强制转换的类型的转换。常用的显式
转换包括以下几种。
 显式数值转换,如long类型转换为int类型等。
 显式枚举转换,如int类型转换为枚举类型等。
 显式引用转换,如object类型转换为引用类型等。
 显式接口转换,如object类型转换为接口类型等。
 拆箱转换,如object类型转换为值类型等。
 用户定义的显式转换, 包括以下3个步骤:一个标准的隐
式转换;执行用户定义的显式转换运算符;另一个标准
的隐式转换。
C#从入门到实践
4.8
小结
本章主要介绍了C#语言中的变量的基础知识,如变量概述
、变量分类、变量赋值、值参数、ref参数、out参数、变
量转换等。其中,读者要着重掌握变量赋值、值参数、
ref参数、out参数和变量转换,为后续编写C#程序代码奠
定基础。下一章将要介绍C#语言中的表达式和运算符。
C#从入门到实践
4.9 习题
在Visual Studio 2008集成开发环境中创建名称为“Test_04”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“ValueF”的方法,且该方法使用值参
数value。
(3)创建一个名称为“RefF”的方法,且该方法使用ref参
数value。
(4)创建一个名称为“OutF”的方法,且该方法使用out参
数value。
C#从入门到实践
第5章
表达式和运算符
表达式是C#语言组成的重要元素之一,它是可以计算且结
果为单个值、对象、方法或命名空间的代码片段。表达
式也可以包含文本值、方法调用、运算符及其操作数,
或简单名称。简单的说,表达式是一个由操作数和运算
符组成的序列。本章将讲解C#语言中的表达式和运算符
,主要介绍以下知识点。
 表达式分类;
 this、base和new关键字;
 运算符;
 运算检查;
 运算符重载。
C#从入门到实践
5.1
表达式
表达式是一个由操作数(operand)和运算符(operator)
构成的序列。运算符指定操作数的运算规则,即指示对
表达式中的操作数进行什么样的运算。本节将介绍表达
式的知识点。
C#从入门到实践
5.1.1
表达式分类
在C#语言中,可以把表达式分为以下9种类别,如表5.1所示。
表达式类型
说明
值
每一个值都有关联的类型。
变量
每一个变量都有关联的类型。如果该变量存在了相关的类型,
则称该变量为已声明类型的变量。
命名空间
C#程序是利用命名空间组织起来的。
类型
指定变量数据的存储方式和操作方法。
方法组
表示一组方法,并可以通过实例调用方法组中的方法。
属性访问
每个属性访问都有关联的类型,即该属性的类型。
事件访问
每个事件访问都有关联的类型,即该事件的类型。
索引器访问
每个索引器访问都有关联的类型,即该索引器的元素类型。
Nothing
出现在调用一个具有void返回类型的方法时。
C#从入门到实践
5.1.2
this关键字
this关键字可以用来引用类的当前实例,还可以用作扩展方
法的第一个参数的修饰符。this关键字存在以下3种常用
用法。
1.限定名称相同的成员
2.将对象本身作为参数
3.声明索引器
C#从入门到实践
5.1.3
base关键字
base关键字用于从派生类中访问基类的成员,主要存在以下
2种用法。
 调用基类上已被其他方法重写的方法。
 指定创建派生类实例时应调用的基类构造函数。
base关键字之后一般跟着“.”标记和一个标识符或一个用方
括号括起来的表达式列表。
C#从入门到实践
5.1.4
new关键字
new关键字可以作为new运算符、new修饰符或new约束。
1.new运算符
2.new修饰符
3.new约束
C#从入门到实践
5.2
运算符
运算符是表达式很重要的一部分,它指示对表达式中的操作
数进行什么样的运算,如+、-、*、/、%等。根据运算符
所需操作数的个数,可以把运算符分为以下3类。本节介
绍运算符的知识点。
 一元运算符,只带有一个操作数并使用前缀表示法(如-x)或后缀表示法(如x++),如++、--等运算符。
 二元运算符,带有两个操作数并且全都使用中缀表示法
(如x+y),如+、-、*、/等运算符。
 三元运算符,带有3个操作数并使用中缀表示法,如?: 运
算符。
C#从入门到实践
5.2.1
运算符优先级
算术表达式是最为常见的一种表达式。它由操作数和运算符
组成,而且这些运算符之间是存在一定优先级的,如*运
算符的优先级就大于+运算符的优先级。C#语言中的运算
符一样,也存在优先级。在计算表达式的值时,也必须
遵循运算符的优先级的规则。
C#从入门到实践
5.2.2
一元运算符
+、-、!、~、++x、--x和(T)x被称为一元运算符。其中,
(T)x运算符为强制转换运算符,它可以将一种类型转换为
另外一种类型。+、-和~运算符分别表示一元加运算、一
元减运算和按位求补运算。下面详细介绍!、++x、--x和
(T)x运算符的使用方法。
1.++运算符
2.--运算符
3.!运算符
4.(T)x运算符
C#从入门到实践
5.2.3
算术运算符
*、/、%、+和–运算符称为算术运算符,它们分别表示乘法
、除法、余数、加法和减法运算。语法如下。
left expression operator right expression
left expression和right expression分别表示左操作数和右操作
数,operator表示运算符,可以为*、/、%、+和–。
C#从入门到实践
5.2.4
逻辑运算符
&、^和|运算符称为逻辑运算符。&运算符计算两个操作数
的按位逻辑AND,|运算符计算两个操作数的按位逻辑OR
,^运算符计算两个操作数的按位逻辑XOR。语法如下。
left expression operator right expression
left expression和right expression分别表示左操作数和右操作
数,operator表示运算符,可以为&、^和|。
C#从入门到实践
5.2.5
条件运算符
?:运算符称为条件运算符,它是C#语言中唯一的一个三元运
算符,语法如下。
条件表达式 ? resulta : resultb;
该表达式首先计算条件表达式的值。如果条件表达式的值为
真,则resulta的值,并成为运算结果。否则计算resultb
,并成为运算结果。
C#从入门到实践
5.2.6
条件逻辑运算符
&&和||运算符称为条件逻辑运算符。&&运算符为逻辑与运
算符,它计算左右操作数的逻辑与。||运算符为逻辑或运
算符,它计算左右操作数的逻辑或。语法如下。
left expression operator right expression
left expression和right expression分别表示左操作数和右操作
数,operator表示运算符,可以为&&和||。
C#从入门到实践
5.2.7
移位运算符
<<和>>运算符被称为移位运算符。<<运算符表示左移位,
>>运算符表示右移位。语法如下:
erpression operator count;
expression表示被移位的表达式,count表示移动的位数,
operator表示运算符,可以为<<和>>。
C#从入门到实践
5.2.8
关系和类型测试运算符
==、!=、<、>、<=、>=、is和as运算符称为关系和类型测试运算
符。语法如下:
left expression operator right expression
left expression和right expression分别表示左操作数和右操作数,
operator表示运算符,可以为==、!=、<、>、<=、>=、is和as
。其中,==、!=、<、>、<=和>=运算符为比较运算符,它们
的具体计算方法如下:
x == y,如果x等于y,则为true,否则为false。
x != y,如果x不等于y,则为true,否则为false。
x < y,如果x小于y,则为true,否则为false。
x > y,如果x大于y,则为true,否则为false。
x <= y,如果x小于等于y,则为true,否则为false。
x >= y,如果x大于等于y,则为true,否则为false。
C#从入门到实践
5.2.9
赋值运算符
=、*=、/=、%=、+=、-=、<<=、>>=、&=、^=和|=运算符
被称为赋值运算符,它们能够为变量、属性、事件或索
引器元素赋新值。语法如下:
left expression operator right expression
left expression和right expression分别表示左操作数和右操作
数,operator表示运算符,如=、*=、/=等。
C#从入门到实践
5.3
实例一:使用checked和unchecked运算
符检查运算
【实例5-1】演示了使用checked和unchecked运算符检查运
算的方法。该功能由static void CheckCompute()静态函数
实现。
C#从入门到实践
5.4
实例二:复数运算符重载
在C#语言中,所有一元和二元运算符都具有可自动用于任何表达
式的预定义实现。除了预定义运算操作之外,还可通过在类或结构
中设置operator声明来引入用户定义的运算操作。这一技术被称为
运算符重载。
注意:用户定义的运算符操作的优先级总是高于预定义运算符操作
的优先级。
运算符重载可以分为一元运算符重载和二元运算符重载,重载方法
如表5.3所示。
运算符表示法
重载函数表示法
说明
op x
operator op(x)
op为运算符
x op
operator op(x)
x op y
operator op(x,y)
C#从入门到实践
5.5
小结
本章主要介绍了C#语言中的表达式和运算符,如表达式分
类、this关键字、base关键字、new关键字、运算符、运
算符重载等。其中,读者要着重掌握表达式、运算符和
运算符重载,为后续编写C#程序代码奠定基础。下一章
将要介绍C#语言中的语句。
C#从入门到实践
5.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_05”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“Sum”的方法,且在该方法中使用
checked和unchecked运算符检查计算两个数的和的运算
操作。
C#从入门到实践
第6章
语句
和其他编程开发语言(如C、C++等)一样,C#语言也是由
各种各样的语句有序构建而成的。语句可以声明局部变
量或常量,调用方法,创建对象,将值赋予变量、属性
或字段等。一般地,语句以;(分号)终止。本章将讲解
C#语言中的各种语句,主要介绍以下知识点。
 基本语句;
 跳转语句;
 选择语句;
 迭代语句;
 其他语句。
C#从入门到实践
6.1
语句概述
和其他程序开发语言一样,C#语言也提供了多种语句。C#
语言的语句可以分为以下3个大类:
 标记语句,给语句加上一个标签作为前缀。
 声明语句,用来声明局部变量或常量
 嵌入语句,能够嵌入到本身语句或其他语句中执行的语
句。
C#从入门到实践
6.2
基本语句
C#语言包含多种常用的基本语句,如空语句、标记语句、
表达式语句、声明语句、块等。本节将详细介绍创建这
些语句的方法。
C#从入门到实践
6.2.1
空语句
顾名思义,空语句(empty statement)不包括任何实际性语
句,它什么都不做。空语句的语法形式如下:
;
当在要求有语句的上下文中不执行任何操作时,使用空语句
C#从入门到实践
6.2.2
标记语句
标记语句(labeled statement)可以给语句加上一个标签作
为前缀,它可以出现在块(第6.2.5节)中,但是不允许
它们作为嵌入语句。标记语句的语法形式如下:
identifier : statement;
identifier为标签的名称。在同一个块中,不能存在两个同名
的标签,否则会产生编译错误。statement表示被标签标
记的语句。
C#从入门到实践
6.2.3
表达式语句
表达式语句是C#语言程序代码中最为常见的一种语句,它
用来计算所给定表达式的值,而且由该表达式计算的值
将被丢弃。实际上,表达式的值只是一个中间结果。表
达式语句包括以下7类语句:
 赋值表达式,如“i = 2008;”等。
 调用表达式,如“Count();”等。
 创建对象表达式,如“object o = new object();”等。
 前缀递减表达式,如“-- i”等。
 前缀递增表达式,如“++ i”等。
 后缀递减表达式,如“i --”等。
 后缀递增表达式,如“i ++”等。
C#从入门到实践
6.2.4
声明语句
声明语句用来声明局部变量或常量,它可以出现在块(第
6.2.5节)中,但不允许它们作为嵌入语句使用。声明语
句包括声明局部变量语句和声明局部常量语句。声明局
部变量语句用来声明一个局部变量。
C#从入门到实践
6.2.5
块
块(block)用于编写多条语句,并且可以将整个块看成一
个单个语句。块的语法形式如下:
{ statement-list }
statement-list为一个语句列表,它是可选的。如果不存在
statement-list,则称该块是空的。语句列表是由一个或多
个顺序编写的语句组成。
C#从入门到实践
6.3
跳转语句
跳转语句(jump statement)用于无条件地转移程序的控制
,它包括以下5种跳转语句:
 break语句,用于退出直接封闭它所在的switch(第6.4.2
小节中介绍)、while(第6.5.3小节中介绍)、do(第
6.5.4小节中介绍)、for(第6.5.1小节中介绍)或foreach
语句(第6.5.2小节中介绍)。
 continue语句,用于开始直接封闭它的while、do、for或
foreach语句的一次新循环。
 return语句,一般用于函数成员的返回操作,即将控制返
回到函数成员的调用方。
 throw语句,用于产生一个异常。
 goto语句,跳转到指定的标签位置。
C#从入门到实践
6.3.1
break语句
break语句用于退出直接封闭它所在的switch、while、do、
for或foreach语句。它的语法形式如下:
break;
注意:break语句只能用在switch、while、do、for或foreach
语句中,否则发生编译时错误。
如果break语句位于多层嵌套的switch、while、do、for或
foreach语句中,break语句只能应用于最里层的语句。
C#从入门到实践
6.3.2
continue语句
continue语句用于开始直接封闭它的while、do、for或
foreach语句的一次新迭代。它的语法形式如下:
continue;
注意:continue语句只能用在while、do、for或foreach语句
中,否则发生编译时错误。
如果continue语句位于多层嵌套的while、do、for或foreach
语句中,continue语句只能应用于最里层的语句。
C#从入门到实践
6.3.3
return语句
return语句一般用于函数成员的返回操作,即将控制返回到
函数成员的调用方。它的语法形式如下:
return expressionopt;
expressionopt为返回值的表达式,它是一个可选表达式。
return语句存在以下两种形式:
 不带expressionopt表达式的return语句,只能用在返回类
型为void的函数成员、属性的set访问器(第8章)、事件
的add和remove访问器(第8章)、实例构造函数(第8章
)、静态构造函数(第8章)或析构函数(第8章)中。
 带expressionopt表达式的return语句,只能用在返回类型
不是void的函数成员、属性的get访问器(第8章)。
expressionopt表达式必须能够隐式转换为其所在函数成员
的返回类型。
C#从入门到实践
6.3.4
throw语句
throw语句用来引发一个异常。它的语法形式如下:
throw expressionopt;
expressionopt为返回值的表达式,它是一个可选表达式。和
return语句一样,throw语句也分为以下两种形式:
不带表达式的throw语句,只能用在catch块(第6.6.1节)中
,它将重新引发当前正由该catch块处理的那个异常。
带表达式的throw语句,通过expressionopt表达式产生异常
的值。而且,该异常的值的类型必须为System.Exception
类型或者从System.Exception类派生的类型。
C#从入门到实践
6.4
选择语句
选择语句是指根据表达式的值从若干个给定的语句中选择一
个来执行的语句。选择语句包括if语句和switch语句。每
一个if语句的选择支只有2个,而每一个switch语句的选择
支可以为1个或多个。本节将详细介绍if语句和switch语句
。
C#从入门到实践
6.4.1
if语句
if语句能够根据布尔表达式的值选择要执行的语句,它存在
以下2种语法形式。
if(布尔表达式) 嵌入语句;
if(布尔表达式) 嵌入语句1; else嵌入语句2;
布尔表达式
布尔表达式
true
false
嵌入语句1
嵌入语句2
true
嵌入语句
false
C#从入门到实践
6.4.2
switch语句
switch语句比if语句更加灵活,它可以存在1个或多个可执行
的选择支。它的语法形式如下:
switch(表达式)
{
表达式
case常量表达式1:语句块1;
case常量表达式2:语句块2;
…
...
语句块1
语句块2
语句块n
default: 语句块n;
}
表达式的值等于常量表达
式1的值
表达式的值等于常量表达
式2的值
表达式的值不等于常量表达
式1~n中的任何一个的值
C#从入门到实践
6.5
迭代语句
迭代语句是指可以重复执行嵌入语句的语句,包括for语句
、foreach语句、while语句和do语句。本节将详细介绍这
4中迭代语句。
C#从入门到实践
6.5.1
for语句
for语句首先计算一个初始化表达式序列,然后,当某个条
件为真时,重复执行相关的嵌入语句并计算一个迭代表
达式序列。for语句的语法形式如下:
for (初始化表达式; 条件表达式; 迭代表达式) 嵌入语句;
条件表达式
true
嵌入语句
false
C#从入门到实践
6.5.2
foreach语句
foreach语句用于枚举一个集合的元素,并对该集合中的每
个元素执行一次相关的嵌入语句。foreach语句的语法形
式如下:
foreach (类型 迭代变量 in 表达式) 嵌入语句;
是否是expression的
最后一个元素
false
嵌入语句
true
C#从入门到实践
6.5.3
while语句
while语句能够按照不同条件执行一个嵌入语句零次或多次
,它的语法形式如下:
while (布尔表达式) 嵌入语句;
布尔表达式
true
嵌入语句
false
C#从入门到实践
6.5.4
do语句
do语句和while语句非常相似,它能够按照不同条件执行一
个嵌入语句一次或多次。它的语法形式如下:
do 嵌入语句 while (布尔表达式);
如果布尔表达式的值为true,则执行嵌入语句。do语句按照
如下规则执行,执行的流程图如图6.7所示。
true
嵌入语句
布尔表达式
false
C#从入门到实践
6.6
其他语句
其他语句主要包括try语句、using语句、lock语句、checked
语句、unchecked语句等。本节将详细介绍这些语句的使
用方法。
C#从入门到实践
6.6.1
try语句
try语句提供一种机制,可以用来捕捉在块的执行期间发生的各种
异常。此外,try语句还能指定一个代码块,并保证当控制离开
try语句时,总是先执行该代码。
一个try语句可能包含try块、catch块和finally块。try块一般包含
需要恢复或清理操作的代码,即有可能发生异常的代码。catch
块一般包括出现异常时需要执行的响应代码。finally块一般包
括确保一定执行的代码,如资源清理操作等。
对于一个try语句而言,try块是必须的,而且只能是一个,catch
块和finally块不是必须的。一个try语句存在以下3种形式:
 一个try块,后跟一个或多个catch块。
 一个try块,后跟一个finally块。
 一个try块,后跟一个或多个catch块,后面再跟一个finally块。
C#从入门到实践
6.6.2
using语句
using语句用来定义一个范围,并在该范围之外释放一个或
多个对象,即用于获取一个或多个资源,并执行一个语
句,然后释放该资源。它的语法形式如下:
using (resource-acquisition) embedded-statement
resource-acquisition用于获取一个或多个资源,表示该资源
的对象必须实现了System.IDisposable的类或结构。
embedded-statement为一个嵌入语句,当using语句获取
其资源之后,将执行该嵌入语句。
执行using语句时,一般包括3个步骤:获取资源、使用资源
和释放资源。using语句最常见的形式如下所示。
using (ResourceType resource = expression) statement
C#从入门到实践
6.6.3
lock语句
lock语句用于首先获取某个给定对象的互斥锁,即对该对象
进行加锁。然后执行一个语句,最后释放该锁。它的语
法形式如下:
lock (expression) embedded-statement
expression表示被加锁的对象,且必须为引用类型的对象;
embedded-statement表示加锁过程中执行的语句。
C#从入门到实践
6.6.4
checked和unchecked语句
checked语句和unchecked语句用于控制整型算术运算和转换
的溢出检查上下文。checked语句和unchecked语句完全
等效于checked运算符和unchecked运算符(第5.3节)。
不同的是,checked语句和unchecked语句用于块,而不
是表达式。
C#从入门到实践
6.7
实例一:判断闰年
【实例6-1】演示了使用if语句判断指定的年份是否为闰年。
该功能由IsLeapYear(int year)静态函数(year参数类型为
int,表示年份)实现。其中,判断指定的年份是否为闰
年的规则如下。
 能被4整除而不能被100整除的年份,则是闰年。
 能被400整除的年份,则是闰年。
不满足上述任何一个条件的年份,则不是闰年。
C#从入门到实践
6.8
小结
本章主要介绍了C#语言中的语句,如基本语句、跳转语句
、选择语句、迭代语句、其他语句等。其中,读者要着
重掌握基本语句、跳转语句、选择语句和迭代语句,为
后续编写C#程序代码奠定基础。下一章将要介绍C#语言
中的命名空间。
C#从入门到实践
6.9
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_06”的控制台应用程
序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“IFStatement”的方法,且在该方法中使用if语句。
(3)创建一个名称为“SwitchStatement”的方法,且在该方法中使用switch
语句。
(4)创建一个名称为“ForStatement”的方法,且在该方法中使用for语句。
(5)创建一个名称为“ForeachStatement”的方法,且在该方法中使用
foreach语句。
(6)创建一个名称为“WhileStatement”的方法,且在该方法中使用while语
句。
(7)创建一个名称为“DoStatement”的方法,且在该方法中使用do语句。
(8)创建一个名称为“TryStatement”的方法,且在该方法中使用try语句。
C#从入门到实践
第7章
命名空间
C#语言的程序是利用命名空间(namespace)组织起来的,
它为C#语言的类型系统提供唯一的完全限定名称。命名
空间既用作程序的“内部”组织系统,也用作“外部”
组织系统(相对于其他程序而言的,一种用来公开程序
本身所拥有元素的方法)。本章将讲解C#语言的命名空
间,主要介绍以下知识点。
 声明命名空间;
 .(点号)运算符;
 ::(双冒号)运算符;
 using指令;
 .NET Framework常用命名空间。
C#从入门到实践
7.1
命名空间概述
命名空间(namespace)是一种用于组织C#程序代码中的不
同类型的方式,并使类型具有唯一的完全限定名称。在
概念上,命名空间和计算机文件系统中的文件夹比较类
似。命名空间具有以下4个用途。
 组织大型代码项目。
 使用.运算符将它们分隔。
 using指令不必为每个类指定命名空间的名称。
 global命名空间是.NET Framework应用程序的“根”命
名空间,global::System始终引用.NET Framework中的
System命名空间。
C#从入门到实践
7.2
声明命名空间
namespace关键字用于声明一个范围,并称该范围为命名空间。通
过命名空间可以组织程序的源代码,并为源代码提供一个全局
唯一类型访问的方法。声明命名空间的具体语法如下。
namespace qualified-identifier
{
body
[;]
}
qualified-identifier表示命名空间的名称,该名称必须唯一,body
表示该命名空间的内容主体(该部分是不可缺少的),;(分号
)是一个可选项。一旦声明了一个命名空间之后,该命名空间
中的主体源代码将在该命名空间中进行编译。
C#从入门到实践
7.3
.(点号)运算符
.(点号)运算符用于成员访问。在命名空间中,.(点号)
运算符指定命名空间的成员。【示例7-7】使用.(点号)
运算符访问了System命名空间下的Int32类型,并声明了
该类型的i变量。
System.Int32 i;
C#从入门到实践
7.4
::(双冒号)运算符
::(双冒号)运算符用于在指定命名空间中查找标识符,它
通常放置在两个标识符之间。【示例7-10】使用::(双冒
号)运算符在global命名空间中查找System.Console类,
并调用WriteLine()方法在控制台上显示“This is a
string.”字符串。
global::System.Console.WriteLine("This is a string.");
注意:global表示在全局命名空间中的查找,而不是在个别
特定的命名空间中查找。
C#从入门到实践
7.5
using指令
using关键字存在两种常用用法:作为指令和作为语句。当
using关键字作为指令时,它用于为命名空间或类型创建
别名或导入其他命名空间中定义的类型。当using关键字
作为语句时,它用于定义一个范围,并在此范围的末尾
将释放对象。本节介绍using关键字作为指令的详细用法
。
C#从入门到实践
7.5.1
创建命名空间或类型别名
using指令可以为一个命名空间或类型创建特定的、简单的
别名,使得通过该别名也可以引用该命名空间或类型。
具体语法如下:
using old-identifier = new- identifier;
old-identifier表示命名空间或类型的旧名称,new- identifier
表示该命名空间或类型的新名称,即别名。
C#从入门到实践
7.5.2
导入命名空间
using指令还可以将一个命名空间中所包含的类型导入到指
定的程序体或文件中,从而该程序体或文件中的代码可
以直接访问该命名空间中的类型,而不需要加上类型的
完全限定符(如命名空间的名称)。具体语法如下:
using identifier;
identifier表示被导入的命名空间。
C#从入门到实践
7.6
.NET Framework常用命名空间
Microsoft .NET Framework类库(Class Library)是一个综
合性的面向对象的可重用类型集合,由.NET Framework
SDK中的类、接口、值类型等组成的库。.NET
Framework类库是创建.NET Framework应用程序、组件
和控件的基础,并为开发人员提供了大量的命名空间、
类等基础技术。
C#从入门到实践
7.7
小结
本章主要介绍了C#语言中的命名空间,如声明命名空间、.
(点号)运算符、::(双冒号)运算符、using指令、
.NET Framework常用命名空间等。其中,读者要着重掌
握声明命名空间、using指令和.NET Framework常用命名
空间,为后续编写C#程序代码奠定基础。下一章将要介
绍C#语言中的类。
C#从入门到实践
7.8
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_07”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)设置class1.cs文件的命名空间为“MyTest_07_01”。
(3)将名称为“class2.cs”的文件添加到该应用程序中。
(4)设置class2.cs文件的命名空间为“MyTest_07_02”。
C#从入门到实践
第8章
类
C#是面向对象的编程语言,它使用类和结构来实现类型(
如Windows窗体、ASP.NET Web窗体、用户界面控件等
)。典型的C#应用程序由程序员定义的类和.NET
Framework的类组成。本章将讲解C#语言中的类,主要
介绍以下知识点。
 类概述;
 类数据成员;
 类函数成员
 创建派生类;
 展示类的多态性。
C#从入门到实践
8.1
类概述
类(class)是一种数据结构,它可以包含数据成员(常量和
字段)、函数成员(方法、属性、事件、索引器、运算
符、实例构造函数、静态构造函数和析构函数)以及嵌
套类型。类类型支持继承,继承是一种机制,它使派生
类可以对基类进行扩展和专用化。
C#从入门到实践
8.1.1
类声明
声明类需要使用class关键字,语法如下。
class-modifiers class identifier class-base class-body ;
class-modifiers表示类修饰符(可选),identifier表示类的
名称,class-base表示类的基类或接口等(可选),classbody表示类体,;(分号)是可选的。
C#从入门到实践
8.1.2
类修饰符
类修饰符放在class关键字的前面,它包括new、public、
protected、internal、private、abstract和sealed共7个关键
字。其中,public、protected、internal和private修饰符控
制类的可访问性。它们的意义具体说明如下。
 public修饰符表示该类是公开的,访问不受限制。
 protected修饰符表示该类只能是本身或其派生的类访问。
 internal修饰符表示该类只能是在当前应用程序中访问。
 private修饰符表示该类只能是本身访问。
C#从入门到实践
8.1.3
类继承
类类型支持继承(inherit),继承是一种机制,它使派生类
可以对基类进行扩展和专用化。在类声明语法中,classbase表示类的基类或接口等(可选),即一个类可以从另
外一个类继承而来。
C#从入门到实践
8.1.4
类、对象和实例化
类是一种数据结构,它为动态创建类的实例提供了定义。类
的实例又称为对象。实例化是一种操作,它可以为类的
实例分配内存。
C#从入门到实践
8.2
类成员
类可以包含多种成员,如常量、字段、方法等,具体说明如下。
(1)常量
(2)字段
(3)方法
(4)属性
(5)事件
(6)索引器
(7)运算符
(8)实例构造函数
(9)析构函数
(10)静态构造函数
(11)类型
上述成员除了类型之外,可以分类两大类:数据成员和函数成员
。其中,数据成员包括常量和字段;函数成员包括方法、属性
、事件、索引器、运算符、实例构造函数、析构函数和该类的
静态构造函数。本节将详细介绍上述类的成员。
C#从入门到实践
8.2.1
常量
常量(constant)用来表示常数值,它的值在编译时计算。
常量的类型必须为sbyte、byte、short、ushort、int、uint
、long、ulong、char、float、double、decimal、bool、
string、枚举类型或引用类型。
在声明常量时,需要使用const关键字。
C#从入门到实践
8.2.2
字段
字段(field)是类中最为常见的数据成员,它为类中的变量
。如果在同一个语句中同时声明多个字段,那么字段之
间需要使用,(逗号)分隔。根据字段的修饰方式,可以
把字段分为以下4种。
 静态字段,使用static修饰,对应于静态变量。
 实例字段,不使用static修饰,对应于实例变量。
 只读字段,使用readonly修饰。
 易失字段,使用volatile修饰。该类型的字段很少使用,
在此不做详细介绍。
C#从入门到实践
8.2.3
方法
方法(method)是包含一系列语句的代码块,通过这些代
码块能够实现预先定义的计算或操作。方法一般声明在
类或结构中,由访问级别、返回值、方法名称、方法参
数和方法体组成。其中,访问级别、返回值、方法名称
和方法参数统称为方法的“签名”。方法参数包括在小
括弧(“()”)中,多个参数使用,(逗号)分隔。如
果为空括号,则表示该方法不需要参数。
1.方法参数
2.静态方法和实例方法
3.虚方法和重写方法
4.密封方法
5.抽象方法
C#从入门到实践
8.2.4
属性
属性(property)是C#语言所特有的一种机制,它可以用于
访问对象或类的特性的成员。属性和字段非常相似,而
且访问属性和字段的语法相同。但是,属性不表示存储
位置(字段表示一个存储位置)。
属性通过一种被称为访问器的机制来获取或修改其值。其中
,获取属性的值的访问器为称为get访问器,修改属性的
值的访问器被称为set访问器,它们的具体说明如下:
 get访问器相当于一个无参数方法,且该访问的返回值的
类型和属性的类型相同。在get访问器中,必须包含
return语句,返回该属性的值。
 set访问器相当于一个返回类型为void的方法,且该方法
只有一个参数,参数的类型和属性的类型相同。特别地
,该方法的参数名称始终约定为value。
C#从入门到实践
8.2.5
索引器
索引器(indexer)其实是一种含有参数的属性,又称为含
参属性。它提供索引的方式来访问对象,即与数组的访
问方式相同。声明索引器时,需要使用this关键字。
C#从入门到实践
8.2.6
构造函数
构造函数是类的一种特定的方法,它的名称和其所属类的名
称相同。构造函数是在创建给定类型的对象时执行的类
方法,通常用来初始化新对象的数据成员,即设置数据
成员的默认值。在任何时候,只要创建类,就会调用它
的构造函数。如果开发人员没有为类显式提供构造函数
,则默认情鱿C#编译器将为该类创建一个默认的构造函
数
1.实例构造函数
2.静态构造函数
C#从入门到实践
8.2.7
析构函数
析构函数(destructor)是一种用于实现销毁类实例所需操
作的成员。它和类的构造函数恰恰相反,类的构造函数
用来初始化该类的实例,而析构函数用来释放该类的实
例占用的资源,并销毁该类的实例。
析构函数的名称和类的名称一样,并带有“~”字符。
C#从入门到实践
8.2.8
事件
事件(event)是一种使对象或类能够提供通知的成员。客
户端可以通过提供事件处理程序(event handler)为相应
的事件添加可执行代码。类或对象可以通过事件向其他
类或对象通知发生的相关事情。
一个类或对象可以事先向其他类或对象注册一个事件,然后
在一定的时候引发该事件。如开发人员可以向在
Windows窗体中的按钮注册一个事件,当用户单击该按
钮时,将引发该已注册的事件。有关事件的知识点将在
第12章中详细介绍。
C#从入门到实践
8.3
实例一:使用类的继承特性
本实例创建了3个类:Person、Teacher和Student。Teacher
和Student类都继承与Person类,它们的继承关系如图8.1
所示。
C#从入门到实践
8.3.1
设计Person类
Person类包含3个字段:name、age和courses。其中,name
字段表示姓名,类型为string;age字段表示年龄,类型
为int;courses字段表示课程列表,它为一个元素类型为
string的数组。
C#从入门到实践
8.3.2
设计Teacher类
Teacher类继承于Person类,且还包含1个字段:duty。该字
段表示职务,类型为string。
C#从入门到实践
8.3.3
设计Student类
Student类继承于Person类,且还包含1个字段:className
。该字段表示班级,类型为string。
C#从入门到实践
8.3.4
测试Person、Teacher和Student类
【实例8-1】测试Person、Teacher和Student类,并介绍了类
的使用方法。
C#从入门到实践
8.4
小结
本章主要介绍了C#语言中的类,如类概述、类数据成员、
类函数成员、派生类、多态性等。其中,读者要着重掌
握类的数据成员和函数成员,以及使用类的派生和多态
性来创建派生类的方法,为后续编写C#程序代码奠定基
础。下一章将要介绍C#语言中的结构。
C#从入门到实践
8.5
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_08”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“MyClass”的类,并在该类中定义如
下成员。





sum常量;
value字段;
GetValue()方法;
Index属性;
只包含一个类型为int的参数、且返回类型为string的索引器;
 printHandler事件。
C#从入门到实践
第9章
结构
结构和类非常相似。和类相比,结构更加适合用于表示轻量
级对象(如复数、坐标、矩阵、颜色等)。通过结构,
只要使用少量数据成员,就能够表示这些轻量级对象,
从而简化了应用程序。本章将讲解C#语言中的结构,主
要介绍以下知识点。
 结构概述;
 结构成员;
 结构和类的区别
 创建Point结构;
 创建Complex结构。
C#从入门到实践
9.1
结构概述
结构(struct)与类非常相似,它们都表示可以包含数据成
员(常量和字段)和函数成员(方法、属性、事件、索
引器、运算符、实例构造函数和静态构造函数)的数据
结构。但是,结构是一种值类型,结构类型的变量直接
包含了该结构的数据。类类型是一种引用类型,类类型
1.结构声明
2.结构修饰符
C#从入门到实践
9.2
结构成员
结构和类一样,它也包含多种成员,如常量、字段、方法等,具体说明
如下。
 常量
 字段
 方法
 属性
 事件
 索引器
 运算符
 实例构造函数
 静态构造函数
 类型
上述成员除了类型之外,可以分类两大类:数据成员和函数成员。其中
,数据成员包括常量和字段;函数成员包括方法、属性、事件、索引
器、运算符、实例构造函数和静态构造函数。
C#从入门到实践
9.3
结构和类的区别
结构和类虽然比较相似,但是还存在以下8个方面的区别。
结构是值类型,并隐式地从类System.ValueType继承,而类是引用类型,并从类
object继承。
结构总是分配在堆栈上,而类常常分配在堆上。如果对结构类型的变量进行赋值
,那么将创建所赋的值的一个副本。
结构类型字段的默认值是字段本身的类型的默认值,而类类型字段的默认值为null
。因此,结构是存在默认值的。
结构不能声明无参数的实例构造函数。
结构不能声明析构函数。
在结构中,初始化实例字段是错误的。
对于结构而言,不像类那样存在继承。一个结构不能从另一个结构或类继承,而
且不能作为一个类的基。但是,结构从基类Object继承。结构可实现接口,其
方式同类完全一样。
实例化结构时,可以不使用new运算符,而且结构对象的字段具有默认初始值。而
实例化类时,必须使用new运算符,并需要设置各个字段的初始值。
C#从入门到实践
9.3.1
继承
结构不支持继承。因此,在声明结构成员时,不能使用
protected或protected internal修饰符。结构类型永远不会
是抽象的,并且始终是隐式密封的。因此,结构不能作
为其他结构或类的基结构,而且在声明结构时,不能使
用abstract或sealed修饰符。
C#从入门到实践
9.3.2
this保留字
this是一个保留字,它只能在实例构造函数、实例方法或实
例访问器的块中使用,且表示当前实例。在类中,this表
示当前实例,它的值不能被修改。在结构中,this相当于
一个变量。如果在结构的实例构造函数中,this相当于一
个结构类型的out参数;如果在结构的实例函数成员中,
this相当于一个结构类型的ref参数。
C#从入门到实践
9.3.3
构造函数
在结构中,不能声明无参数的实例构造函数。其实,每一个
结构都隐式地具有一个无参数实例构造函数,该构造函
数将初始化该结构所有字段的值。如果字段的类型为值
类型,则将该字段的值设置为其类型的默认值。如果字
段的类型为引用类型,则将该字段的值设置为null。
另外,结构还可以声明带有参数的实例构造函数。
C#从入门到实践
9.4
实例一:创建坐标点结构Point
本实例创建一个名称为Point的结构,用来表示二维坐标值
。该结构包含2个属性:X和Y,它们分别表示X坐标值和
Y坐标值。
C#从入门到实践
9.4.1
设计Point结构
Point结构包含2个字段:x和y。其中,x字段表示X坐标的值
,y字段表示Y坐标的值,它们的类型都为int。
C#从入门到实践
9.4.2
测试Point结构
【实例9-1】测试了Point结构,并使用该结构创建一个实例
p,然后显示该实例的X坐标和Y坐标的值。
C#从入门到实践
9.5
实例二:创建复数结构Complex
本实例创建一个名称为Complex的结构,用来表示一个复数
。该结构包含2个属性:Integer和Fraction,它们分别表
示复数的整数部分和小数部分。另外,该结构重载了+运
算符,并使用该运算符计算了两个复数的和。
C#从入门到实践
9.5.1
设计Complex结构
Complex结构包含2个字段:integer和fraction。其中,
integer字段表示复数的整数部分,fraction字段表示复数
的小数部分,它们的类型都为int。
C#从入门到实践
9.5.2
测试Complex结构
【实例9-2】测试了Complex结构,并使用该结构创建两个
实例lc和rc,然后计算这两个实例的和,并显示计算结果
。
C#从入门到实践
9.6
小结
本章主要介绍了C#语言中的结构,如结构概述、结构成员
、结构和类的区别、Point结构、Complex结构等。其中
,读者要着重掌握结构的成员,以及创建结构的方法,
为后续编写C#程序代码奠定基础。下一章将要介绍C#语
言中的数组。
C#从入门到实践
9.7
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_09”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“MyStruct”的类,并在该类中定义如
下成员。
 sum常量;
 value字段;
 GetValue()方法;
 Index属性;
 只包含一个类型为int的参数、且返回类型为string的索引
器;
 printHandler事件。
C#从入门到实践
第10章
数组
数组可以将多个类型相同的元素组合为一个整体,从而通过
数组统一访问或操作这些元素。数组是C#语言最常用的
数据结构之一。它是相同数据类型的对象的集合。该集
合的长度(即数组的长度)可以为0或大于0的整数。本
章将讲解使用数组进行编程的方法,主要介绍以下知识
点。
 数组概述;
 数组分类;
 静态数组;
 动态数组;
 抽签程序。
C#从入门到实践
10.1
数组概述
数组是一个有序的数据集合。数组中的每一个元素的数据类
型都相同。元素的数据类型被称为元素类型,它可以为
任何类型,甚至可以为数组。数组可以用一个统一的数
组名和下标来唯一确定组中的元素。例如,一个班有50
名学生,可以用s1、s2、s3、…、s50表示50个学生的成绩
。s为数组名,下标表示学生的序号。s10(整数10为下标
)表示第10个学生的成绩。
C#从入门到实践
10.1.1
数组的维度数
大家都知道,直线由点构成,平面由直线构成、空间由平面
构成。如果要描述直线上的一个点,则只需要一个值。
如果要描述平面上的一个点,则需要两个值。如果要描
述空间中的一个点,则需要3个值。在直线、平面和空间
中,称描述一个点所需要值的数量为“维度数”。
数组也一样,它也存在维度数的概念。当在要描述数组中的
一个元素时,如果只需要一个值(数组的下标),那么
该数组的维度数为1;如果需要两个值,那么该数组的维
度数为2;依次类推。如上述提及的s数组的维度数就是1
。根据数组的维度数不同,可以把数组分为以下3种类型
 一维数组,维度数为1的数组。
 二维数组,维度数为2的数组。
 多维数组,维度数大于2的数组。
C#从入门到实践
10.1.2
声明数组
在C#程序设计中,如果需要某一个数组,则必须首先声明
该数组。声明一维数组的语法如下所示。
type[] arrayName;
其中,type表示数组元素的类型,如int、double、string、
object等;arrayName表示数组的名称。
C#从入门到实践
10.1.3
实例化数组
实例化数组就是为数组分配相应的内存。注意,声明一个数
组,并不为该数组分配相应的内存。
C#从入门到实践
10.1.4
初始化数组
初始化数组就是初始化数组中每一个元素的值,即为数组中
的每一个元素进行赋值。数组被实例化之后,每个元素
都为其元素类型的默认值。一般情况下,只有初始化数
组之后,该数组才具有实际运算的意义。初始化数组存
有多种方法,主要包括以下4种。
1.直接赋值
2.使用“new”操作符,并指定了数组的长度
3.使用“new”操作符,省略数组的长度
4.直接设置数组的每一个元素的值
C#从入门到实践
10.1.5
遍历数组
遍历数组是指依次访问数组中的每一个元素,并执行预先设
计的操作。访问数组的元素最常用方法之一就是使用下
标(或索引)。根据是否使用下标可以遍历数组方式分
为两种。第一种,使用下标遍历,如for、while、
do…while等语句。第二种,不使用下标遍历,如foreach
语句。
1.使用下标遍历数组
2.不使用下标遍历数组
C#从入门到实践
10.2
数组分类
根据数组的维度数和元素的类型不同,可以把数组分为4种
类型:一维数组(维度数为1的数组)、二维数组(维度
数为2的数组)、多维数组(维度数大于2的数组)和交
错数组(元素的类型为数组的数组)。本小节将介绍声
明、实例化和初始化各种不同类型数组的方法。
C#从入门到实践
10.2.1
一维数组
一维数组是指维度数为1的数组,它是最简单的数组,也是
最常用的数组。声明一维数组的语法如下所示。
type[] arrayName;
其中,type表示数组元素的类型,如int、double、string、
object等;arrayName表示数组的名称。
C#从入门到实践
10.2.2
二维数组
二维数组是指维度数为2的数组。声明二维数组的语法如下
所示。
type[,] arrayName;
其中,type表示数组元素的类型,如int、double、string、
object等;中括号([])中间存在一个逗号(,)表示该数
组为一个二维数组;arrayName表示数组的名称。
C#从入门到实践
10.2.3
多维数组
多维数组是指维度数大于2的数组,如三维数组、四维数组
等。声明三维数组的语法如下所示。
type[, ,] arrayName;
其中,type表示数组元素的类型,如int、double、string、
object等;中括号([])中间存在两个逗号(,)表示该数
组为一个三维数组;arrayName表示数组的名称。
C#从入门到实践
10.2.4
交错数组
交错数组又称为“数组的数组”,它的元素也为一个数组。
声明二维交错数组的语法如下所示。
type[][] arrayName;
其中,type表示数组元素的类型,如int、double、string、
object等;type关键字之后包含两个中括号([])表示该
数组为一个二维交错数组;arrayName表示数组的名称。
C#从入门到实践
10.3
静态数组System.Array
.NET框架提供了两种数组:静态数组和动态数组。一旦为
数组分配内存之后,如果该数组的大小是不能修改的,
则称该数组为静态数组;反之,则称之为动态数组。静
态数组静态数组由System.Array类实现,动态数组由
System.ArrayList类实现。本小节将介绍静态数组的基本
属性和方法,以及它们的使用方法。
注意:本章前面小节所介绍的数组都是属于静态数组。
C#从入门到实践
10.3.1
属性
System.Array类包含7个属性,如获取数组长度的Length属性、获
取数组秩的Rank等,如表10.1所示。
属性
描述
Length
数组的长度,即数组所有维度中元素的总数。
该值为32位整数。
LongLength
数组的长度,即数组所有维度中元素的总数。
该值为64位整数。
Rank
数组的秩,即数组的维度数。
IsFixedSize
表示数组的大小是否固定。
IsReadOnly
表示数组是否为只读。
IsSynchronized
表示是否同步访问数组。
SyncRoot
获取同步访问数组的对象。
C#从入门到实践
10.3.2
方法
System.Array类包含多个方法,如获取数组长度的GetLength()方法
、获取指定元素值的GetValue()方法,获取指定元素索引的
IndexOf()方法等,如表10.2所示。
属性
描述
GetValue()
获取指定元素的值。
SetValue()
设置指定元素的值。
Clear()
清空数组中的所有元素。
GetLength()
获取指定维的元素数量。该值为32位整数。
GetLongLength()
获取指定维的元素数量。该值为64位整数。
IndexOf()
获取匹配的第一个元素的索引。
LastIndexOf()
获取匹配的最后一个元素的索引。
FindIndex()
搜索指定元素,并获取第一个匹配元素的索引。
FindLastIndex()
搜索指定元素,并获取最后一个匹配元素的索引。
Copy()
将一个数组中的一部分元素复制到另一个数组。
CopyTo()
将一维数组的所有元素复制到另外一个一维数组。
Clone()
复制数组。
ConstrainedCopy()
指定开始位置,并复制一系列元素到另外一个数组中。
Sort()
对一维数组中的元素进行排序。
Reverse()
反转一维数组中元素的顺序。
BinarySearch()
使用二进制搜索算法在一维的排序数组中搜索指定元素。
GetLowerBound()
获取数组中指定维度的下限。
GetUpperBound()
获取数组中指定维度的上限。
C#从入门到实践
10.3.3
获取数组长度
数组长度是指数组元素的总数,即数组每一维度元素数量之
乘积。获取数组长度的方法存在多种,可以通过
System.Array类的属性获取,也可以通过Array类的方法
获取。
1.通过属性获取数组的长度
2.通过方法获取数组的长度
C#从入门到实践
10.3.4
获取元素的值
获取数组中指定元素的值最简单方法就是通过“[]”运算符
。
C#从入门到实践
10.3.5
设置元素的值
和获取指定元素的值一样,也存在两种方法设置元素的值。
第一种方法就是直接通过数组名和“[]”运算符来设置元
素的值。
C#从入门到实践
10.3.6
获取元素的索引
System.Array类为一维数组提供了获取元素的索引的两个静
态方法:IndexOf()和LastIndexOf()方法。IndexOf()方法
获取匹配的、第一个元素的索引。LastIndexOf()方法获
取匹配的、最后一个元素的索引。
C#从入门到实践
10.3.7
排序数组
System.Array类为一维数组提供了一个名称为“Sort()”的方
法,该方法可以对一维数组中的元素进行排序。能够使
用Sort()方法排序的数组中的元素必须实现IComparable
接口,即数组中的元素是能够进行比较的,否则不能对
该数组中的元素进行排序。
C#从入门到实践
10.3.8
反转数组
System.Array类为一维数组提供了一个名称为“Reverse()”
的方法,该方法可以反转一维数组中的全部元素或部分
连续的元素。
C#从入门到实践
10.4
动态数组System.ArrayList
动态数组又称为可变数组,且数组的长度可以动态修改。动
态数组由System.ArrayList类实现,它在保存元素时,仅
仅保存元素的引用,而不是元素的具体值。因此,动态
数组元素的数据类型可以是任何类型,而且各个元素的
数据类型也可以不相同。
C#从入门到实践
10.4.1
属性
System.ArrayList类包含了7个属性,如获取数组元素数量的Count
属性、指示数组是否为只读的ReadOnly属性等,如表10.3所示。
属性
描述
Capacity
数组的容量。
Count
数组元素的数量。
Item
指定索引处的元素。
IsFixedSize
表示数组的大小是否固定。
IsReadOnly
表示数组是否为只读。
IsSynchronized
表示是否同步访问数组。
SyncRoot
获取同步访问数组的对象。
C#从入门到实践
10.4.2
方法
System.ArrayList类包含了多个方法,如添加新元素到数组
末尾中的Add()方法、从数组中删除指定元素的Remove()
方法等。
C#从入门到实践
10.4.3
添加元素
向动态数组添加一个新的元素可以使用Add()方法或者
Insert()方法。Add()方法可以将新的元素添加到数组的末
尾处,Insert()方法可以将新的元素添加到数组的指定位
置。如果希望把新的元素插入到数组(元素数量大于0)
的开始处,则只能使用Insert()方法。
C#从入门到实践
10.4.4
移除元素
如果要从动态数组中移除元素,则可以使用Remove()、
RemoveAt()或RemoveRange()方法。Remove()方法从数
组中移除指定的元素,RemoveAt()方法从数组中移除指
定位置处的元素,RemoveRange()方法从数组中移除指定
范围内的元素。
C#从入门到实践
10.5
实例一:抽签程序
【实例10-1】使用整型数组实现抽签功能。该功能由
Draw(int count)函数实现,count参数表示签号的总数量
。
C#从入门到实践
10.6
小结
本章主要介绍了C#语言中的数组,如数组概述、数组分类
、静态数组、动态数组、抽签程序等。其中,读者要着
重掌握数组分类、一维数组、静态数组和动态数组,以
及使用数组编程的方法,为后续编写C#程序代码奠定基
础。下一章将要介绍C#语言中的接口。
C#从入门到实践
10.7
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_10”的
控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“UsingArray”的类,并在该类中定义如
下成员,并使用这些成员测试Array类的各个方法的用途。
 名称为“values1”的、元素类型为int的一维数组;
 名称为“values2”的、元素类型为string的一维数组;
 名称为“values3”的、元素类型为int的二维数组;
 名称为“values4”的、元素类型为string的一维数组;
 名称为“values5”的、元素类型为int的三维数组;
 名称为“values6”的、元素类型为int的交错数组。
C#从入门到实践
第11章
接口
接口和类一样,也是属于引用类型。接口可以用来描述属于
类或结构的一组相关功能,即定义一种协议。类或结构
可以实现接口,同时必须遵循它们所实现接口定义的协
议。本章将讲解C#语言中的接口,主要介绍以下知识点
。
 接口概述;
 接口成员;
 实现接口;
 抽象类和接口。
C#从入门到实践
11.1
接口概述
接口(interface)定义一种协议,实现该接口的类或结构必
须遵循该协议。一个接口可以继承于一个或多个其他接
口,一个类或结构也可以实现一个或多个接口。接口可
以包含4种成员:方法、属性、事件和索引器。接口本身
不提供它所定义的成员的实现,它仅仅指定实现该接口
的类或结构必须提供的成员。
C#从入门到实践
11.1.1
接口声明
声明接口需要使用interface关键字,语法如下。
interface-modifiers interface identifier interface-base
interface-body ;
interface-modifiers表示接口修饰符(可选),identifier表示
接口的名称,interface-base表示接口的基接口(可选)
,interface-body表示接口体,;(分号)是可选的。4
C#从入门到实践
11.1.2
接口修饰符
接口修饰符一般位于接口声明中的interface关键字之前,共
包括5个修饰符:new、public、protected、internal和
private。其中,public、protected、internal和private修
饰符控制接口的可访问性。它们的意义具体说明如下。
 public修饰符,表示该接口是公开的,访问不受限制。
 protected修饰符,表示该接口只能是本身或其派生的接
口访问。
 internal修饰符,表示该接口只能是在当前应用程序中访
问。
 private修饰符,表示该接口只能是本身访问。
C#从入门到实践
11.1.3
接口继承
接口可以继承于一个或多个其他接口,也可以不继承。被继
承的接口称为该接口的显式基接口。当一个接口具有一
个或多个显式基接口时,在声明该接口时,接口标识符
后就要紧跟一个冒号和一个由,(逗号)分隔的基接口标
识符列表。
C#从入门到实践
11.2
接口成员
接口的成员必须是方法、属性、事件或索引器,而不能包括
常量、字段、运算符、实例构造函数、析构函数或类型
,也不能包含任何种类的静态成员。一个接口可以不包
括任何成员,也可以包括一个或多个成员。接口成员默
认隐式地具有public访问属性,而且在声明接口成员时不
能包含任何修饰符(如abstract、public、protected、
internal、private、virtual、override和static),否则会
发生编译时错误。
注意:一个接口的成员包括两部分:由接口本身声明的成员
和其从基接口继承的成员。
C#从入门到实践
11.2.1
属性
在接口中声明属性时,只能声明该属性具有哪个访问器(如
get或set访问器),而不能实现该访问器。接口属性的访
问器只用于表明该属性是只读的、只写的还是读写的,
访问器体必须始终是一个;(分号)。
C#从入门到实践
11.2.2
索引器
接口索引器和接口属性比较相似。在接口中声明索引器时,
只能声明该索引器具有哪个访问器(如get或set访问器)
,而不能实现该访问器。接口索引器的访问器只用于表
明该索引器是只读的、只写的还是读写的,访问器体必
须始终是一个;(分号)。
C#从入门到实践
11.2.3
方法
在接口中声明方法时,只能声明该方法的签名,而且该方法
的方法体只能为;(分号),而不能包括该方法的实现代
码。
C#从入门到实践
11.2.4
事件
在接口中声明事件时,只能声明该事件的签名,而且事件的
名称之后必须接一个;(分号)。
C#从入门到实践
11.3
实现接口
类和结构都可以实现接口。如果某一个类或接口实现了一个
或多个接口,那么在声明该类或结构时,将实现的接口
的标识符包含在该类或结构的基类列表中。
C#从入门到实践
11.3.1
实现属性
实现接口属性即添加该接口属性的实现代码,接口属性的名
称和实现该接口属性的名称相同。
C#从入门到实践
11.3.2
实现索引器
实现接口索引器即添加该接口索引器的实现代码。
C#从入门到实践
11.3.3
实现方法
实现接口方法即添加该接口方法的实现代码,接口方法的名
称和实现该接口方法的签名相同。
C#从入门到实践
11.3.4
实现事件
实现接口事件即添加该接口事件的实现代码,接口事件的名
称和实现该接口事件的签名相同。
C#从入门到实践
11.4
抽象类和接口
抽象类使用abstract修饰符,它用于表示所修饰的类是不完
整的,并且它只能用作基类。抽象类与非抽象类在以下3
个方面的区别。
 抽象类不能直接实例化。如果抽象类使用new运算符,则
发生编译时错误。
 允许(但不要求)抽象类包含抽象成员。
 抽象类不能被密封。
当从抽象类派生非抽象类时,这些非抽象类必须实现所继承
的所有抽象成员,即重写这些抽象成员。
C#从入门到实践
11.5
实例一:设计算术计算接口
【实例11-1】设计了用于算术计算的ICompute接口。该接
口包括4个方法,具体说明如下。
 double Add(double leftValue,double rightValue),计算两
个数的和。
 double Sub(double leftValue,double rightValue),计算两
个数的差。
 double Multiply(double leftValue,double rightValue),计
算两个数的积。
 double Div(double leftValue,double rightValue),计算两
个数的商。
C#从入门到实践
11.6
小结
本章主要介绍了C#语言中的接口,如接口概述、接口成员
、实现接口,抽象类和接口区别等。其中,读者要着重
掌握接口成员和实现接口的方法,为后续编写C#程序代
码奠定基础。下一章将要介绍C#语言中的委托和事件。
C#从入门到实践
11.7
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_11”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“MyInterface”的接口,并在该接口
中定义属性、索引器、方法、事件等成员。
C#从入门到实践
第12章
委托和事件
委托是C#语言中一种引用方法的类型,和C++中处理函数指针的情
况比较相似。不但可以向委托实例注册方法列表,而且还可以通
过委托实例来调用方法列表中的方法。事件是一种特殊的委托,
它包含两个参数:指示事件源的“对象源”参数和封装事件的其
他任何相关信息的“e”参数。本章将讲解C#语言中的委托和事件
,主要介绍以下知识点。
 声明委托;
 委托实例化;
 委托调用;
 声明事件;
 注册事件和移除事件;
 调用事件。
C#从入门到实践
12.1
委托
熟悉C++中函数指针的读者可能比较容易理解委托。委托(
delegate)是一种数据结构,它是用来处理类似于C++中
函数指针的情况,即委托能够引用静态方法或引用类实
例及其实例方法。特别地,委托是完全面向对象的,同
时也封装了对象实例和方法。
所有委托类型的基类是System.Delegate类。System.Delegate
类本身不是委托类型,而且不允许显式地直接从该来派
生新的类型。委托实例封装了一个调用列表,该列表包
含了一个或多个方法,每个方法称为一个可调用实体。
C#从入门到实践
12.1.1
委托声明
委托类型的声明将创建一个协定,该协定指定一个或多个方法的
签名。委托是委托类型的实例,它可以引用静态方法或者实例
方法。声明委托需要使用delegate关键字,语法如下。
delegate-modifiers delegate return-type identifier
delegate-modifiers表示委托的修饰符(可选),它包括new、
public、protected、internal和private共5个关键字。其中,
public、protected、internal和private修饰符控制委托的可访问
性。它们的意义具体说明如下。
 public修饰符,表示该委托是公开的,访问不受限制。
 protected修饰符,表示该委托只能是本身委托访问。
 internal修饰符,表示该委托只能是在当前应用程序中访问。
 private修饰符,表示该委托只能是本身访问。
C#从入门到实践
12.1.2
创建向委托注册方法
一旦声明一个委托之后,那么就指定了该委托方法列表中的
方法签名,包括方法列表中的方法的返回类型和方法参
数。如果一个方法能够注册到某一个委托中,那个该方
法的签名必须与该委托的所指定的签名完全匹配。匹配
规则如下。
 方法的返回类型必须和委托的返回类型相同。
 方法的方法参数必须和委托的方法参数相同,参数的具
体名称可以不相同。
C#从入门到实践
12.1.3
委托实例化
委托实例化可以创建委托类型的实例,并向该实例注册方法
列表。委托类型的实例的方法列表可以为静态方法、实
例方法或者另外一个委托实例。
注意:委托实例化,它把静态方法、实例方法或者另外一个
委托的名称作为该实例的方法参数进行传递。
C#从入门到实践
12.1.4
委托的方法列表
一个委托实例都必须包含其方法列表,方法列表可以包含一
个或多个方法。委托实例除了在其实例化时注册方法之
外,还可以通过“+”或“+=”运算符向该实例的方法列表
中的注册方法,通过“-”或“-=”运算符向该实例的方法
列表中的移除方法
C#从入门到实践
12.1.5
委托调用
一个委托实例的方法列表,又称为该委托实例的调用列表。
一个调用列表可能包含一个或多个方法。如果一个调用
列表包含多个方法时,当该委托实例被调用时,它将按
照调用列表中方法的注册顺序依次调用每一个方法。
C#从入门到实践
12.2
事件
事件(event)是一种使对象或类能够提供通知的成员。客
户端可以通过提供事件处理程序为相应的事件添加可执
行代码。客户端可以实现为事件定义一些操作或方法,
当事件发生时,将调用该事件事先定义的操作或方法。
C#从入门到实践
12.2.1
声明事件
事件其实是一种特殊类型的委托,它包含两个参数:指示事
件源的“对象源”参数和封装事件的其他任何相关信息
的“e”参数。其中,“e”参数的类型为System.EventArgs
类型或从System.EventArgs类派生的类型。声明事件一般
包括以下两个步骤。
(1)声明事件的委托。
(2)声明事件本身。
C#从入门到实践
12.2.2
注册事件
一个事件一旦声明之后,该事件的默认值为null。如果希望
该事件执行事先指定的操作,则首先向该事件注册方法
列表(即委托的调用列表)。注册事件可以使用“+=”运
算符。
C#从入门到实践
12.2.3
移除事件
除了注册事件之外,还可以移除事件。移除事件使用“-=”
运算符。
C#从入门到实践
12.2.4
调用事件
声明一个事件之后,如果没有向该事件注册方法,那么该事
件的值为空(null)。因此,在调用事件时,往往需要检
查该事件是否为空。
C#从入门到实践
12.3
实例一:测试打印事件
【实例12-1】演示了测试打印事件的方法。该功能由
TestPrintEvent类和PrintEventHandler委托实现。
C#从入门到实践
12.4
小结
本章主要介绍了C#语言中的委托和事件,如声明委托、委
托实例化、委托调用、声明事件、注册事件、移除事件
、调用事件等。其中,读者要着重掌握声明委托、委托
调用、声明事件、注册事件和调用事件,为后续编写C#
程序代码奠定基础。下一章将要介绍C#语言中的异常处
理。
C#从入门到实践
12.5
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_12”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“PrintEventHandler”的委托,并使
用该委托定义名称为“PrintEvent”的事件,然后测试该
事件的使用方法。
C#从入门到实践
第13章
异常处理
异常是程序执行时遇到的任何错误情况或意外行为。应用程
序必须能够统一处理在执行期间发生的错误。.NET
Framework公共语言运行库提供了一个模型,以统一的
方式通知程序发生的错误。本章将讲解C#语言中的异常
处理机制,主要介绍以下知识点。
 异常概述;
 try语句;
 System.Exception类;
 .NET Framework常用异常类;
 创建自定义异常类。
C#从入门到实践
13.1
异常概述
和C++程序语言一样,C#程序语言也存在异常处理机制。
C#程序语言中的异常用于处理系统级和应用程序级的错
误状态,它是一种结构化的、统一的和类型安全的处理
机制。
C#从入门到实践
13.1.1
导致异常的原因
在应用程序运行时,发生异常的原因是多种多样的,如除数
为0、堆栈溢出等。导致异常的原因可以归纳为以下2大
类。
 在执行语句和表达式(C#语言)的过程中,有时会出现
一些例外情况,从而使得某些操作无法正常完成,此时
就会引发一个异常。
 应用程序使用throw语句特意产生一个异常,此时将引发
一个异常。
C#从入门到实践
13.1.2
try语句
try语句可以用来捕捉在代码块的执行期间发生的各种异常
。它可以包含try块、catch块和finally块,具体说明如下
。
 try块,一般包含有可能发生异常的代码。
 catch块,包含出现异常时需要执行的响应代码。
 finally块,包含出现异常时一定执行的代码,如资源清理
等操作。
C#从入门到实践
13.1.3
异常处理
异常是由try语句处理的。当发生异常时,系统将搜索与当
前try块相关的最近的、可以处理该异常的catch块,然后
由该catch块处理该异常。如果与当前try块相关的所有
catch块都不能处理该异常,则沿着堆栈向上搜索封闭该
异常代码的try块及其相关联的catch块,如果找到,则由
该catch块处理该异常。如果还没有找到catch块,则重复
上述过程,直到找到catch块。如果到达调用堆栈顶部仍
然没有找到处理该异常的catch块,则由默认的异常处理
程序处理该异常,然后应用程序终止。
C#从入门到实践
13.2
System.Exception类
System.Exception类表示在应用程序执行期间发生的错误,它是
.NET Framework中所有异常的基类型。当系统或应用程序
发生错误时,将通过引发包含错误信息的异常来报告错误。
一旦异常发生后,将由该应用程序或默认异常处理程序(如
System.Exception类)来处理异常。
System.Exception类包含描述错误的可读文本。当异常发生时,
应用程序的运行库(如.NET Framework)将产生消息(保
存在Exception类的实例的Message属性中)通知用户错误的
性质并提供解决该问题的操作建议。Exception类包括以下两
类异常。
 从SystemException派生的预定义公共语言运行库异常类。
 从ApplicationException派生的用户定义的应用程序异常类。
C#从入门到实践
13.3
常用异常类
.NET Framework提供了10个常用异常类,如处理空(null)引用的
System.NullReferenceException类、处理数组索引小于0或超过其下标
的System.IndexOutOfRangeException类等。这些常用异常类及其说明
如表13.3所示。
类
描述
System.NullReferenceException
如果使用null引用,引发此异常。
System.IndexOutOfRangeException
如果使用小于零或超出数组界限的下标访问数组时,引发该异常。
System.InvalidCastException
如果显式转换失败时,就会引发此异常。
System.DivideByZeroException
当除数为0时,引发该异常。
System.StackOverflowException
当堆栈溢出(如无限递归)时,引发该异常。
System.OverflowException
在checked上下文中的算术运算溢出时,引发该异常。
System.OutOfMemoryException
在通过new操作分配内存失败时,引发该异常。
System.ArithmeticException
在算术运算期间发生错误时,引发该异常。
System.TypeInitializationException
静态构造函数引发异常,且没有可以捕捉到它的catch子句时,引发该异
常。
System.ArrayTypeMismatchException
如果被存储的元素的实际类型与数组的元素类型不兼容时,引发此异常。
C#从入门到实践
13.4
实例一:自定义异常处理类
本实例创建了一个自定义异常处理类,它的名称为
CustomException,并直接继承于System.Exception类。
CustomException类声明了一个名称为ErrorCode的属性
,表示错误代码。因此,使用CustomException类处理异
常,可以为异常添加错误代码。
C#从入门到实践
13.4.1
设计CustomException类
CustomException类包含1个字段:errorCode,表示错误代
码,类型为int。程序代码如下。
public class CustomException:System.Exception
{
private int errorCode = 10001;
C#从入门到实践
13.4.2
使用CustomException类处理异常
【实例13-1】使用CustomException类处理异常,并介绍了
使用CustomException类产生异常并捕获该类产生异常的
方法。
C#从入门到实践
13.5
小结
本章主要介绍了C#语言中的异常,如异常概述、try语句、
System.Exception类、.NET Framework常用异常类、自
定义异常类等。其中,读者要着重掌握try语句,以及处
理异常的方法,为后续编写C#程序代码奠定基础。下一
章将要介绍C#语言中的泛型。
C#从入门到实践
13.6 习题
在Visual Studio 2008集成开发环境中创建名称为“Test_13”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“MyException”的类(继承于
Exception),并使用该类处理自定义的异常。
C#从入门到实践
第14章
泛型
泛型(Generic)是具有占位符(类型参数)的类、结构、
接口和方法,这些占位符是类、结构、接口和方法所存
储或使用的一个或多个类型的占位符。泛型集合类可以
将类型参数用作它所存储的对象的类型的占位符;类型
参数作为其字段的类型和其方法的参数类型出现。泛型
方法可以将其类型参数用作其返回值的类型或者其形参
的类型之一。本章将讲解C#语言中的泛型,主要介绍以
下知识点 。
 泛型概述;
 泛型方法;
 创建泛型列表
 创建泛型堆栈。
C#从入门到实践
14.1
泛型概述
使用过C++模板的读者可能熟悉泛型(Generic)这一概念
。C#中的泛型能够将类型作为参数来传递,即在创建类
型时,事先使用一个特定的符号(如T等)代替实际的类
型,在创建该类型的实例时,才指定T的实际类型。
泛型可以让类、结构、接口、委托和方法按它们存储和操作
的数据的类型进行参数化。泛型能提供更强的编译时类
型检查,减少数据类型之间的显式转换,以及装箱操作
和运行时的类型检查。
使用泛型类型可以最大限度地重用代码、保护类型的安全以
及提高性能。泛型最常见的用途是创建集合类。.NET
Framework类库在System.Collections.Generic命名空间中
包含多个新的泛型集合类,如List<T>、Stack<T>、
Queue<T>等。当然,开发人员也可以创建自定义泛型类
型。
C#从入门到实践
14.1.1
泛型类声明
泛型类声明也是一种类的声明,因此,泛型类声明也遵循类
声明的规则。一个泛型类一般至少包含一个类型形参(
14.1.2小节中介绍)。当创建该泛型类的实例时,需要指
定该类型形参的具体类型。
C#从入门到实践
14.1.2
类型形参
类型形参放置在类名后,并在“<”和“>”分隔符中指定。类
型形参仅仅是一个简单标识符,是将来提供的类型的形
式占位符。换句话说,T类型形参只起占位符的作用,直
到在使用时才为其指定了实际类型。
每一个类型形参所代表的实际类型由其所在实例创建时指定
。特别地,该实例将存储类型形参的数据而不进行数据
类型转换。
C#从入门到实践
14.1.3
类型形参的约束
通常地,类型形参的类型可以指定为任何类型。然而,一些
类型形参需要指定一定种类的类型,如结构、类等。为
了实现该功能,就需要限制类型形参的类型,这种限制
被称为约束。即在定义泛型类时,可以限制在实例化类
时用于类型参数的类型种类。如果尝试使用某个约束所
不允许的类型来实例化类,则会产生编译时错误。
C#从入门到实践
14.1.4
泛型类的成员
泛型类的所有成员都可以直接使用其所属类的类型形参。在
运行时,类型形参都被替换为相应的实际类型(该类型
在创建类的实例时指定)。
C#从入门到实践
14.1.5
泛型类的静态字段
在泛型类中,静态字段的共享方法比较特殊,即只有在具有
相同类型形参的类型的实例才能够共享同一个静态字段
的值。
C#从入门到实践
14.2
泛型方法
泛型方法(Generic Method)是使用类型参数声明的方法,
它可以声明在类、结构或接口中,而这些类、结构或接
口本身可以是泛型或非泛型的。如果这些类、结构或接
口也是泛型类型时,那么在这些方法内既可以引用该泛
型方法的类型形参,也可以使用这些类、结构或接口的
类型形参。
C#从入门到实践
14.2.1
声明泛型方法
和普通方法相比,除了普通的参数之外,泛型方法还必须包
含类型形参,即泛型方法是指在声明中包含类型形参的
方法。
C#从入门到实践
14.2.2
调用泛型方法
泛型方法调用可以显式指定类型实参列表,或者可以省略类
型实参列表并依赖类型推断确定类型实参。通常地,调
用泛型方法和调用普通方法一样,但需要为类型形参提
供相应的类型实参列表。
C#从入门到实践
14.2.3
通过委托调用泛型方法
除了14.3.2中调用泛型方法的方法之外,还可以通过委托来
调用泛型方法。
C#从入门到实践
14.2.4
虚泛型方法
和普通方法一样,泛型方法也存在虚泛型方法,它也可以使
用abstract、virtual和override修饰符进行声明。
C#从入门到实践
14.3
实例一:实现泛型列表
本实例首先创建了名称为“GenericList<T>”的泛型类(保
存在GenericList.cs文件中),并为该类提供5个方法:
Add(T item)、Remove(T item)、RemoveAt(int index)、
Clear()和Sort(IComparer<T> c);然后创建该类的实例
list,并介绍了GenericList<T>类的属性和方法的使用方
法。
C#从入门到实践
14.3.1
设计泛型列表类GenericList<T>
GenericList<T>泛型类为T类型形参添加了约束“where
T:IComparable”,即约束T类型形参的类型必须实现
IComparable接口。GenericList<T>泛型类包含list字段,
表示一个列表,类型为List<T>。程序代码如下。
public class GenericList<T> where T:IComparable
{
/// <summary> 私有字段list,类型为List<T> </summary>
private List<T> list;
C#从入门到实践
14.3.2
测试泛型列表
【实例14-1】测试GenericList<T>类,并创建了该类的实例
list。
C#从入门到实践
14.4
实例二:实现泛型堆栈
本实例首先创建了名称为“GenericStack<T>”的泛型类(保
存在GenericStack.cs文件中),并为该类提供5个方法:
IsEmpty()、Push(T item)、Pop()、Peek()和Clear();然
后创建该类的实例stack,并介绍了GenericStack<T>类的
属性和方法的使用方法。
C#从入门到实践
14.4.1
设计泛型堆栈类GenericStack<T>
GenericStack<T>泛型类为T类型形参添加了约束“where
T:class”,即约束T类型形参的类型必须为引用类型。
GenericStack<T>泛型类包含stack字段,表示一个堆栈,
类型为Stack<T>。
C#从入门到实践
14.4.2
测试泛型堆栈
【实例14-2】测试GenericStack<T>类,并创建了该类的实
例stack。
C#从入门到实践
14.5
小结
本章主要介绍了C#语言中的泛型,如泛型概述、泛型方法
、泛型列表、泛型堆栈等。其中,读者要着重掌握泛型
概述,以及创建泛型类(如泛型列表、泛型堆栈等)的
方法,为后续编写C#程序代码奠定基础。下一章将要介
绍C#语言中的分部类型和可空类型。
C#从入门到实践
14.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_14”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“MyGenericStack”的泛型堆栈,同
时实现堆栈的常用操作,如入栈、出栈、堆栈是否为空
等。
C#从入门到实践
第15章
分部类型和可空类型
分部类型可以将类、结构、接口或者方法的定义拆分为一个
或多个部分,甚至可以保存为多个源文件中。可空类型
可以用来处理值类型的值为空的情况,它能够指示可空
类型的实例是否包含一个确定的值。本章将讲解C#语言
中的分部类型和可空类型,主要介绍以下知识点。
 声明分部类、结构和接口;
 分部类型同名成员处理;
 处理分部类型的基接口;
 可空类型的属性;
 可空类型的方法;
 bool?类型。
C#从入门到实践
15.1
分部类型
分部类型(Partial type)允许将类、结构和接口划分为多个部分
,并存储在不同的源文件中,以便于开发和维护。在Visual
Studio 2008集成开发环境中开发应用程序时,有时一个类(如
Windows窗体、ASP.NET窗体页等)的一部分代码由机器自动
生成,另外一部分代码由程序员编写。如果把这个类设置为分
部类,那么这两部分代码可以保存在不同的源文件中,从而增
加了应用程序的代码的灵活性。
在声明分部类型的每一个部分时,每一个部分都必须包含partial
修饰符,并且分部类型的所有声明代码都必须位于同一命名空
间中。partial修饰符表示它所在的类型可能还包含其他部分,
但是其他部分并不一定是必须的。如果一个类型只包含一个部
分,在声明该类型时使用了partial修饰符,也是正确的。
C#从入门到实践
15.1.1
声明分部类
使用partial修饰符可以用来声明分部类。
C#从入门到实践
15.1.2
声明分部结构
使用partial修饰符可以用来声明分部结构。
C#从入门到实践
15.1.3
声明分部接口
使用partial修饰符除了可以用来声明分部类和结构之外,还
可以用来声明接口。
C#从入门到实践
15.1.4
同名成员处理
如果一个分部类型包含了多个部分,那么该类型的所有成员
为各个部分成员的并集,并且在每一个部分中可以访问
其他部分的成员,即使在声明该成员时使用了private修
饰符。然而,在不同部分中声明了同一个名称的成员,
则发生编译时错误。除非该成员使用了partial修饰符。
C#从入门到实践
15.1.5
处理基接口
如果一个分部类型包含了多个部分,那么该类型的所有基接
口集是每一个部分指定的基接口的并集。一个基接口在
分部类型的一个部分中只能指定一次,但是可以在多个
部分中同时被指定,即多个部分可以同时指定同一个基
接口。
注意:在整个分部类型中,一个基接口的成员的实现只能是
一个。但是,一个部分的基接口可以由另外一个部分提
供该基接口的实现。
C#从入门到实践
15.2
可空类型
可空类型(Nullable)是一个组合了基础类型的值和布尔空
值指示符的结构。可空类型除了表示基础类型的所有值
之外,还可以表示空值(null)。可空类型为值类型,声
明可空类型存在以下两种形式。
(1)使用System.Nullable类声明可空类型
(2)使用?(问号)声明可空类型
C#从入门到实践
15.2.1
HasValue和Value属性
任何可空类型的实例都包含两个公共只读属性:HasValue
和Value。它们的具体意义说明如下。
HasValue属性的类型为bool,它表示该实例是否包含一个确
定值。如果HasValue属性的值为true,则表示该实例包
含一个确定的值。否则,表示该实例为空,即它不包含
确定的值。此时,如果要获取该实例的值,则发生运行
时错误。
Value属性的类型为该可空类型的基础类型,它表示该实例
的一个确定的值,并作为该实例的值。
C#从入门到实践
15.2.2
GetValueOrDefault()方法
可空类型的实例只包含一个方法:GetValueOrDefault(),它
可以用来获取可空类型的实例的值或默认值。它存在以
下两种重载形式。
(1)public T GetValueOrDefault()
(2)public T GetValueOrDefault(T defaultValue)
T表示可空类型的基础类型。如果可空类型的实例的
HasValue属性的值为true,则该方法返回该实例的值(
即Value属性的值)。如果可空类型的实例的HasValue属
性的值为false,(1)方法返回该实例的默认值,(2)
方法返回defaultValue参数的值。
C#从入门到实践
15.2.3
bool?类型
bool?类型为可空布尔类型,它可以表示3个值:true、false和null
。可空布尔类型提供了两个运算符:&和|。&运算符表示逻辑与
,|运算符表示逻辑或。可空布尔类型的实例运算结果如表15.1所
示。
X
Y
X&Y
X|Y
true
true
true
true
true
false
false
true
true
null
null
true
false
true
false
true
false
false
false
false
false
null
false
null
null
true
null
true
null
false
false
null
null
null
null
null
C#从入门到实践
15.3
实例一:测试可空类型
【实例15-1】演示了测试基类型为int的可空类型的方法。该
功能由TestNullableType类实现。
C#从入门到实践
15.4
小结
本章主要介绍了C#语言中的分部类型和可空类型,如声明
分部类、结构和接口、分部类型同名成员处理、处理分
部类型的基接口、可空类型的属性、可空类型的方法、
bool?类型等。其中,读者要着重掌握数组声明分部类和
使用可空类型的方法,为后续编写C#程序代码奠定基础
。下一章将要介绍C#语言中的隐型变量、初始化器、匿
名类型和隐型数组。
C#从入门到实践
15.5
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_15”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个名称为“UsingStringNull”的类,并在该类处
理可以为空的字符串。
C#从入门到实践
第16章
隐型变量、初始化器、匿名类型和隐型数组
隐型局部变量是使用var关键字声明的一种隐藏类型的局部
变量。初始化器包括对象初始化器和集合初始化器,它
们分别用来初始化对象和集合。使用new运算符和匿名对
象初始化器可以创建一个匿名类型的对象;使用var关键
字和匿名数组初始化器可以创建一个隐型数组。本章将
讲解C#语言中的隐型局部变量、对象初始化器、集合初
始化器、匿名类型和隐型数组,主要介绍以下知识点。
 声明隐型局部变量;
 使用隐型局部变量;
 对象初始化器;
 集合初始化器;
 匿名类型;
 隐型数组。
C#从入门到实践
16.1
隐型局部变量
顾名思义,隐型(implicitly typed)局部变量是一个局部变
量,而且它的类型被隐藏了。在隐型局部变量声明中,
正被声明的局部变量的类型可以从初始化该变量的表达
式推导出来。
C#从入门到实践
16.1.1
声明隐型局部变量
声明隐型局部变量需要使用var关键字,并使用var关键字作
为变量的类型。在声明隐型局部变量时,不明确指定该
变量的类型,而是使用var关键字指定变量的类型。该变
量的实际类型将在其初始化表达式中推导出来。
C#从入门到实践
16.1.2
使用隐型局部变量
使用隐型局部变量可以不显式指定变量的类型,从而简化了
程序代码。然而,如果大量使用隐型局部变量,往往可
能造成程序代码难以理解和阅读。因此,只有在适当的
时候使用隐型局部变量,才是一个比较好的选择。隐型
局部变量比较适合以下4种场景。
1.声明隐型局部变量
2.for语句中
3.foreach语句中
4.using语句中
C#从入门到实践
16.2
对象初始化器
对象初始化器(object initializer)又称为对象初始值设定项
,它可以为某个对象的零个或多个字段或属性指定值。
即对象初始化器不显式调用该对象类型的构造函数,就
能够创建该对象类型的实例。
对象初始化器包含一组成员初始值设定项。这一组设定项由
“{”和“}”包围,各个设定项之间用,(逗号)分隔。每
一个成员初始值设定项都为一个赋值表达式,表达式的
左边为成员的名称,表达式的右边是一个可计算的表达
式。“ID = 1”表达式就是一个成员初始值设定项,“{ID
= 1,Name = "Zhangsan"}”表达式就是一组设定项。
C#从入门到实践
16.3
集合初始化器
集合初始化器(collection initializer)又称为集合初始值设
定项,它可以用来设置集合中的元素。集合初始化器包
含一组元素初始值设定项。这一组设定项由“{”和“}”包
围,各个设定项之间用,(逗号)分隔。每一个元素初始
值设定项指定一个元素,“{1,2,3,4,5,6,7,8,9}”表达式就是
一组元素初始值设定项。
C#从入门到实践
16.4
匿名类型
顾名思义,匿名类型是一种隐藏了类型名称的类型,它由
new运算符和匿名对象初始化器共同实现。即使用new运
算符和匿名对象初始化器可以创建一个新的对象,这个
新创建的对象就是一个匿名类型的对象。其中,把new运
算符和匿名对象初始化器组成的表达式又称为匿名对象
创建表达式。
C#从入门到实践
16.5
隐型数组
隐型数组和匿名类型比较相似。和匿名类型的匿名对象初始
化器一样,匿名数组也存在一个匿名数组初始化器。匿
名对象初始化器一般用于创建一个匿名类型的对象,匿
名数组初始化器用来创建一个匿名数组。
匿名数组由var关键字和匿名数组初始化器共同创建,而且
匿名数组初始化器中的元素类型都必须能够隐式转换为
同一个类型(不能为null)。即对于匿名数组初始化器而
言,会存在一种类型(不能为null),使得该匿名数组初
始化器中所有元素都能够转换为该类型的元素。
C#从入门到实践
16.6
实例一:在foreach语句中使用隐型局
部变量
【实例16-1】在foreach语句中使用隐型局部变量遍历元素类型
为string的数组中的每一个元素。该功能由VarForeach()静
态方法实现。
C#从入门到实践
16.7
小结
本章主要介绍了C#语言中的隐型变量、初始化器、匿名类
型和隐型数组,如声明隐型局部变量、使用隐型局部变
量、对象初始化器、集合初始化器、匿名类型、隐型数
组等。其中,读者要着重掌握声明隐型局部变量和使用
隐型局部变量,为后续编写C#程序代码奠定基础。下一
章将要介绍C#语言中的迭代器、匿名方法和扩展方法。
C#从入门到实践
16.8
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_16”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)在该应用程序中使用隐型数组计算0~100(共101个整
数)的和。
C#从入门到实践
第17章
迭代器、匿名方法和扩展方法
迭代器是一个语句块,它可以产生一系列有序值,从而使得
foreach语句可以访问该序列。匿名方法是一种特殊的方
法,它由delegate关键字、参数列表(可选)和包含在
“{”和“}”分隔符中的语句列表组成,并省略了方法的名
称。扩展方法可以向现有的类型“添加”新的方法,它
是一种静态方法,通过扩展类型的实例来调用扩展方法
。本章将讲解C#语言中的迭代器、匿名方法和扩展方法
,主要介绍以下知识点。
 创建非泛型和泛型迭代器;
 非泛型和泛型枚举器;
 创建匿名方法;
 将匿名方法作为参数传递;
 声明扩展方法;
 调用扩展方法。
C#从入门到实践
17.1
迭代器
迭代器(iterator)是一个产生(yield)有序值序列的语句
块(block)。它也可以通过yield关键字对数组或集合类
执行自定义迭代。迭代器包含以下两个特有的语句。
yield return语句,产生迭代的下一个值。
yield break语句,指示迭代完成。
当迭代器执行到yield return语句时,迭代器会保存当前位置
。如果该迭代器再一次被调用时,该迭代器将从上述保
存的位置重新开始执行。迭代器可以产生一系列的值,
而且所有值的类型均相同,该类型称为迭代器的返回类
型,又称为产生类型。
C#从入门到实践
17.1.1
创建非泛型迭代器
IEnumerable接口表示公开枚举数,该枚举数支持在非泛型
集合上进行简单迭代。IEnumerable接口只包含
GetEnumerator()方法,它返回一个循环访问集合的枚举
数。创建一个非泛型迭代器最常用的方法是实现
IEnumerable接口的GetEnumerator()方法。
C#从入门到实践
17.1.2
创建泛型迭代器
如果要创建一个泛型迭代器,往往需要实现IEnumerable和
IEnumerable<T>接口的GetEnumerator()方法。
C#从入门到实践
17.1.3
IEnumerator和IEnumerator<T>接口
IEnumerator表示枚举器的非泛型接口,支持对非泛型集合
的简单迭代。IEnumerator<T>表示枚举器的泛型接口,
支持泛型集合的简单迭代。
1.IEnumerator接口
2.IEnumerator<T>接口
C#从入门到实践
17.2
匿名方法
顾名思义,匿名方法(anonymous method)是一种隐藏了
名称的方法。在C# 2.0版本之前,声明委托的唯一方法是
使用命名方法,即方法必须指定其名称。C# 2.0引入了匿
名方法实现了同样的功能,C# 3.0及其以上版本,使用
Lambda表达式(第18章)取代了匿名方法,它比匿名方
法更加简洁。
匿名方法允许与委托关联的代码以“内联”方式写入使用委
托的位置,从而方便地将代码直接“绑定”到委托实例
。
C#从入门到实践
17.2.1
创建匿名方法
匿名方法由delegate关键字、参数列表(可选)和包含在
“{”和“}”分隔符中的语句列表组成。从匿名方法的组成
元素可以看到,匿名方法已经省略了该方法的名称。
C#从入门到实践
17.2.2
将匿名方法作为参数传递
正是因为匿名方法允许与委托关联的代码以“内联”方式,
从而使得可以将匿名方法作为方法的参数来传递。
C#从入门到实践
17.3
扩展方法
扩展方法可以使得开发人员能够向现有类型“添加”新的方
法,而且不需要创建新的派生类型、重新编译或以其他
方式修改原始类型。扩展方法是一种静态方法,可以通
过扩展类型的实例来调用扩展方法。
C#从入门到实践
17.3.1
声明扩展方法
声明扩展方法时,需要使用this修饰符。扩展方法的第一个
参数指定该方法所作用的类型,并使用this修饰符作为该
参数的前缀。
C#从入门到实践
17.3.2
导入扩展方法
导入扩展方法比较简单,只要使用using指令引入扩展方法
所在的命名空间即可。实际上,被导入的扩展方法作为
其第一个参数的类型上的附加方法。
C#从入门到实践
17.3.3
调用扩展方法
使用using指令导入ToInt32(this string str)扩展方法之后,就
可以调用该扩展方法了。
C#从入门到实践
17.4
实例一:扩展string类型的方法
【实例17-1】为string类型扩展了一个方法,该方法的名称
为“ToInt32(this string str)”,它可以将一个字符串转换
为一个整数。
C#从入门到实践
17.5
小结
本章主要介绍了C#语言中的迭代器、匿名方法和扩展方法
,如创建非泛型和泛型迭代器、非泛型和泛型枚举器、
创建匿名方法、将匿名方法作为参数传递、声明扩展方
法、调用扩展方法等。其中,读者要着重掌握创建非泛
型和泛型迭代器和创建匿名的方法,为后续编写C#程序
代码奠定基础。下一章将要介绍C#语言中的Lambda表达
式和查询表达式。
C#从入门到实践
17.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_17”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)在该应用程序中创建一个泛型迭代器,并使用该迭代
器。
C#从入门到实践
第18章
Lambda表达式和查询表达式
C#提供了一种可以用来查询集合、XML、DataSet(数据集
)和数据库的技术,并使用Lambda表达式和查询表达式
实现这种查询技术。Lambda表达式其实是一种简写的匿
名函数,它可以包含表达式和C#语句。查询表达式是一
种使用查询语法表示的表达式,它可以从一个或多个给
定的数据源中检索数据,并指定检索结果的表现形式。
本章将讲解C#语言中的Lambda表达式和查询表达式,主
要介绍以下知识点。
Lambda表达式;
from子句;
select子句;
where子句;
let子句;
orderby子句;
group子句;
into子句;
join子句。
C#从入门到实践
18.1
Lambda表达式
和匿名方法一样,Lambda表达式也是一种匿名函数(
anonymous function),它可以包含表达式和语句,并且
可用于创建委托或表达式目录树类型。但是,Lambda表
达式比匿名方法具有更加简洁的表示形式。Lambda表达
式可以由输入参数、Lambda运算符和表达式(或语句块
)构成,它的语法形式如下。
(input parameters) => expression;
input parameters表示输入参数,它是可选的;“=>”为
Lambda运算符(读作“goes to”);expression表示表达
式或语句块。
C#从入门到实践
18.1.1
输入参数
在Lambda表达式中,输入参数是Lambda运算符的左边部
分。它包含参数的数量可以为0,1或者多个。当输入参
数的数量为0时,Lambda表达式的左边部分的一对小括
弧不能被省略。
C#从入门到实践
18.1.2
表达式或语句块
在Lambda表达式中,Lambda运算符的右边部分可以是一
个表达式或由多个表达式组成的语句块。
C#从入门到实践
18.2
查询表达式
查询表达式(Query expression)是一种使用查询语法表示
的表达式,由一组类似与SQL或XQuery的声明性语法编
写的子句组成。每一个子句可以包含一个或多个C#表达
式,这些C#表达式本身也可能是查询表达式或包含查询
表达式。查询表达式包括8个基本子句,具体说明如下。
from子句
select子句
where子句
let子句
orderby子句
group子句
into子句
join子句
查询表达式必须以from子句开头,以select或group子句结束
。在第一个from子句和最后一个select子句或group子句
之间,可以包含一个或多个where子句、let子句、join子
句、orderby子句和group子句,甚至还可以是from子句
。
C#从入门到实践
18.2.1
from子句
任何一个查询表达式,不管是否为子查询表达式,它必须包
含from子句,且以from子句开头。from子句用来指定查
询表达式的数据源和范围变量。数据源不但可以包括查
询本身的数据源,而且还可以包括子查询的数据源。范
围变量用来表示数据源序列中的每一个元素。
1.数据源
2.包含单个from子句的查询表达式
3.包含多个from子句的查询表达式
4.包含复合from子句的查询表达式
C#从入门到实践
18.2.2
select子句
select子句指定查询结果的类型和表现形式,即指定将在执
行查询时产生的值的类型。select子句结果及其表现形式
与其前面所有子句的计算结果,以及本身中的所有表达
式相关。一个查询表达式要么以select子句结束,要么以
group子句结束。
C#从入门到实践
18.2.3
where子句
where子句指定筛选元素的逻辑条件,即用来确定从查询表
达式中选择哪些元素。where子句由一个或多个布尔表达
式,以及逻辑运算符(如逻辑与、逻辑或等)组成。一
个查询表达式可以包含一个或多个where子句。在查询表
达式中,where子句不能出现在查询表达式的第一个子句
或最后一个子句的位置,其他任何位置都可以放置where
子句。
C#从入门到实践
18.2.4
let子句
let子句可以创建一个新的范围变量,用来保存查询表达式中
的中间结果。let子句创建的范围变量是一个只读变量,
它的值只能通过初始化操作赋值。一旦设定了范围变量
的值之后,它的值将不能被修改。当然,可以查询该范
围变量的值。
C#从入门到实践
18.2.5
orderby子句
orderby子句可以对查询结果进行排序,排序方式为“升序
”(由ascending关键字指定)和“降序”(由descending
关键字指定)。
C#从入门到实践
18.2.6
group子句
group子句(使用by关键字)可以对查询的结果进行分组,
并返回元素类型为IGrouping<TKey, TElement>的序列。
其中,TKey为分组中键的类型,TElement为分组中元素
的类型。
C#从入门到实践
18.2.7
into子句
into子句可以创建一个临时标识符,并用来保存group子句
、join子句或selet子句的结果,以供其他子句查询该结果
。有时,称在group或select子句中使用新标识符的用法为
“延续”。
C#从入门到实践
18.2.8
join子句
join子句是查询表达式中比较复杂的一个子句,它和SQL语
句中的JOIN子句比较相似,可以用来联接两个数据源,
即设置两个数据源之间的关系。一般情况下,这两个数
据源是存在相关联的属性或值,以供这两个数据源中的
元素进行比较。特别地,join子句可以使用equals关键字
比较元素的指定属性是否相等。join子句支持以下3种常
见联接方式。
 内部联接,元素的联接关系必须同时满足两个数据源,
类似于SQL语句中的INNER JOIN子句。
 分组联接,包含into子句的join子句。
 左外部联接,元素的联接关系必须满足联接中的左数据
源,类似于SQL语句中的LEFT JOIN子句。
C#从入门到实践
18.3
实例一:使用Lambda表达式查询XML
【实例18-1】在QueryXml()方法中介绍使用Lambda表达式
查询XML类的方法。
C#从入门到实践
18.4
小结
本章主要介绍了C#语言中的查询表达式,如Lambda表达式
、from子句、select子句、where子句、let子句、orderby
子句、group子句、into子句、join子句等。其中,读者要
着重掌握Lambda表达式,以及使用Lambda表达式查询
集合、XML文件的方法,为后续编写C#程序代码奠定基
础。下一章将要介绍使用C#语言处理字符串的方法。
C#从入门到实践
18.5
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_18”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)创建一个查询表达式,并使用该查询表达式从一段文
本中查询所有单词。
C#从入门到实践
第19章
字符串处理
字符串类型是C#编程语言中最为常用的一种数据类型,.NET
Framework为字符串提供了丰富地操作和处理方法。通
过这些方法,开发人员可以轻松简单地处理字符串。本
章将讲解.NET Framework中处理字符串的方法,主要介
绍以下知识点。
 String类;
 StringBuilder类;
 不变字符串处理;
 可变字符串处理。
C#从入门到实践
19.1
String和StringBuilder类
在.NET Framework中,字符串可以分为两种类型:不变字
符串(由String类表示)和可变字符串(由StringBuilder
类表示)。不变字符串一旦被创建,那么它的内容是不
能被修改的;而可变字符串被创建之后,它的内容是可
以动态修改的。
C#从入门到实践
19.1.1
String类
String类表示一系列的有序Unicode字符,用来表示文本。
String对象是字符(Char对象)的有序集合,用来表示字
符串。String对象的值是该有序集合的内容,并且该值是
不可变的,即一旦创建了一个String对象,那么就不能修
改该对象的值。虽然有些方法看起来修改了String对象,
而实际上是返回了一个包含修改后内容的新的String对象
。
C#从入门到实践
19.1.2
StringBuilder类
StringBuilder类表示可变字符串,可以创建能够动态修改(
如追加、移除、替换、插入等)的字符串对象。
C#从入门到实践
19.2
不变字符串处理
不变字符串(由String类表示)是不能被修改的。对不变字
符串的每一次处理都将产生一个新的字符串。不变字符
串处理的方法主要包括插入字符串、移除字符串、替换
字符串、联接字符串、分隔字符串、填充字符串等。下
面将详细介绍这些方法。
C#从入门到实践
19.2.1
插入字符串
插入字符串是将新的字符串插入到字符串的指定位置,该功
能由String类的Insert()方法实现。Insert()方法的原型如
下。
public string Insert(int startIndex,string value)
上述方法将value参数指定字符串插入到字符串的startIndex
指定的位置。
startIndex参数表示插入的位置(即索引值),value参数表
示被插入的新字符串。上述方法返回一个新的字符串。
C#从入门到实践
19.2.2
移除字符串
移除字符串是从字符串中指定位置开始移除其后的所有字符
或指定数量的字符,该功能由String类的Remove()方法实
现。Remove()方法的原型如下。
 public string Remove(int startIndex),从startIndex位置
开始移除其后的所有字符。
 public string Remove(int startIndex,int count),从
startIndex位置开始移除其后的数量为count的字符。
C#从入门到实践
19.2.3
替换字符串
替换字符是指将字符串中指定字符替换为新的字符,或者将
指定的字符串替换为新的字符串,该功能由String类的
Replace()方法实现。Replace()方法的原型如下。
 public string Replace(char oldChar,char newChar),将字
符串中指定字符替换为新的字符。
 public string Replace(string oldValue,string newValue),
将字符串中指定字符串替换为新的字符串。
 oldChar参数表示被替换的字符,newChar参数表示替换
后的字符。oldValue参数表示被替换的字符串,
newValue参数表示替换后的字符串。
C#从入门到实践
19.2.4
联接字符串
联接字符串是将一个或多个字符串对象联接为一个新的字符
串,该功能由String类的Concat()方法或Join()方法实现。
其中,Concat()方法的最常用的4种原型如下。
 public static string Concat(object arg0),联接arg0对象的
字符串表示形式,并创建一个新的字符串。
 public static string Concat(string str0,string str1),联接
str0和str1字符串,并创建一个新的字符串。
 public static string Concat(string str0,string str1,string
str2),联接str0、str1和str2字符串,并创建一个新的字
符串。
 public static string Concat(string str0,string str1,string
str2,string str3),联接str0、str1、str2和str3字符串,并
创建一个新的字符串。
C#从入门到实践
19.2.5
分隔字符串
分隔字符串是将一个字符串被指定的分隔字符或字符串分隔为多个子
字符串,并返回由子字符串组成的字符串数组。该功能由String类
的Split()方法实现,它的原型如下。
 public string[] Split(params char[] separator)。
 public string[] Split(char[] separator,int count)。
 public string[] Split(char[] separator,StringSplitOptions options)。
 public string[] Split(string[] separator,StringSplitOptions options)。
 public string[] Split(char[] separator,int count,StringSplitOptions
options)。
 public string[] Split(string[] separator,int count,StringSplitOptions
options)。
C#从入门到实践
19.2.6
填充字符串
填充字符串是向字符串的指定位置填充指定的字符,该功能
由String类的PadRight()和PadLeft()方法实现。其中,
PadRight()方法在字符串的右边填充字符,PadLeft()方法
在字符串的左边填充字符串。由于这两个方法比较相似
,下面只将介绍PadLeft()方法。PadLeft()方法的原型如
下。
 public string PadLeft(int totalWidth),在字符串的左边填
充空白字符,填充之后,新字符串的总长度为totalWidth
 public string PadLeft(int totalWidth,char paddingChar)
,在字符串的左边填充paddingChar字符,填充之后,新
字符串的总长度为totalWidth。
C#从入门到实践
19.2.7
查找字符串
查找字符串是指从字符串中查找指定的字符或子字符串。如
果找到,则返回第一个匹配字符或字符串的索引;否则
返回-1。该功能由String类的IndexOf()和LastIndexOf()方
法实现。其中,IndexOf()方法是从字符串的第一个字符
开始依照从头到尾的方式查找,LastIndexOf()方法从字
符串的最后一个字符开始依照从尾到头的方式查找。
C#从入门到实践
19.2.8
获取子串
获取子串是指从字符串中获取指定的子字符串,该功能由
String类的SubString()方法实现,它的原型如下。
 public string SubString(int startIndex),获取字符串中从
startIndex位置开始的子字符串。
 public string SubString(int startIndex,int length),获取字
符串中从startIndex位置开始的、最大长度为length的子
字符串。
C#从入门到实践
19.2.9
格式化字符串
格式化字符串是指将字符串转化为指定格式的字符串,该功
能由String类的Format()方法实现。
1.数字格式化
2.日期和时间格式化
C#从入门到实践
19.3
可变字符串处理
可变字符串(由StringBuilder类表示)是一种动态字符串,
它是可以被动态修改的。动态修改可变字符串的方法主
要包括插入字符串、追加字符串、移除字符串、替换字
符串、复制字符串等。下面将详细介绍这些方法。
C#从入门到实践
19.3.1
插入字符串
插入字符串是将新的字符串插入到字符串的指定位置,该功
能由StringBuilder类的Insert()方法实现。Insert()方法存
在多种原型,常见的原型如下。
 public StringBuilder Insert(int index,string value),将
value插入到字符串的index指定的位置。
 public StringBuilder Insert(int index,string value,int
count),将value插入到字符串的index指定的位置,并重
复执行该超载count次。
C#从入门到实践
19.3.2
追加字符串
追加字符串是指将指定的字符或字符串追加到字符串的末尾
,该功能由StringBuilder类的Append()、AppendLine()和
AppendFormat()方法实现。其中,AppendLine()方法在
追加指定的字符串之后,还追加一个换行符号;
AppendFormat()方法首先格式化被追加的字符串,然后
将其追加到字符串。下面仅仅介绍Append()方法的用法
。
C#从入门到实践
19.3.3
移除字符串
移除字符串是从字符串中指定位置开始移除其后的指定数量
的字符,该功能由StringBuilder类的Remove()方法实现
,它的原型如下。
 public StringBuilder Remove(int startIndex,int length)。
从字符串中startIndex位置处开始移除其后的count个的字
符
 startIndex参数表示移除的开始位置,count参数表示被移
除字符串的最大字符串数量。
C#从入门到实践
19.3.4
替换字符串
替换字符是指将字符串中指定字符替换为新的字符,或者将
指定的字符串替换为新的字符串,该功能由StringBuilder
类的Replace()方法实现。
C#从入门到实践
19.3.5
复制字符串
复制字符串是指将字符串的内容复制到指定的字符数组中,
该功能由StringBuilder类的CopyTo()方法实现,它的原
型如下。
public void CopyTo(int sourceIndex,char[] destination,int
destinationIndex,int count)。
sourceIndex参数指定被复制字符串中的开始位置;
destination参数指定将字符复制到的字符数组,用来保存
被复制的字符;destinationIndex参数指定保存复制字符
的数组中的起始位置;count参数指定被复制字符的数量
。
C#从入门到实践
19.4
实例一:词频统计
【实例19-1】使用处理字符串的方法统计给定一段文本中所
有单词出现的频率,并按照此频率倒序显示每一个单词
的出现的频率。
C#从入门到实践
19.5
小结
本章主要介绍了使用C#语言处理字符串的方法,如String类
、StringBuilder类、不变字符串处理、可变字符串处理等
。其中,读者要着重掌握不变字符串处理和可变字符串
处理的方法,为后续编写C#程序代码奠定基础。下一章
将要介绍C#语言中的日期和时间处理。
C#从入门到实践
19.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_19”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)在该应用程序分别对静态字符串和动态字符串实现查
找、插入、替换、移除指定字符串的功能。
C#从入门到实践
第20章
日期和时间处理
日期和时间处理是C#编程中最为常见的操作之一。在.NET
Framework中,与日期和时间相关的结构为DateTime和
TimeSpan。DateTime结构表示时间上的某一刻,
TimeSpan结构表示时间间隔。本章将讲解C#编程中的日
期和时间处理,主要介绍以下知识点。
 DateTime结构;
 TimeSpan结构;
 格式化日期和时间;
 计算日期和时间差;
 追加日期和时间。
C#从入门到实践
20.1
DateTime结构
DateTime是一个结构,且为值类型,表示时间上的一刻,
包括日期和时间两部分。DateTime表示的值的范围为公
元0001年1月1日午夜12:00:00到公元9999年12月31日晚上
11:59:59之间的日期和时间。DateTime表示的日期和时间
由年、月、日、时、分、秒,以及分隔符组成。最常用
的一种格式如下所示。
yyyy-MM-dd hh:mm:ss
C#从入门到实践
20.1.1
字段
DateTime结构只包含两个静态只读字段:MaxValue和
MinValue,它们的具体说明如下。
 MaxValue字段,DateTime的最大可能值,它的值为9999
年12月31日 23:59:59.9999999。
 MinValue字段,DateTime的最小可能值,它的值为0001
年1月1日 00:00:00.0000000。
C#从入门到实践
20.1.2
属性
DateTime结构包含16个属性。其中,Now、Today和
UtcNow属性为静态属性,其他属性为实例属性。通过这
16个属性,可以获取时间的值或时间某一个部分的值,
如年份、月份、日期、小时、分钟、秒等。
C#从入门到实践
20.1.3
方法
DateTime结构共包括个38方法,其中,静态方法13个,实
例方法25个。
C#从入门到实践
20.2
TimeSpan结构
TimeSpan结构表示一个时间间隔或持续时间,可以按照正
负天数、小时数、分钟数、秒数以及秒的小数部分进行
度量。
TimeSpan值表示为“[-]d.hh:mm:ss.ff”格式的字符串。减号
(可选)表示负时间间隔;d分量表示天数;hh表示小时
数(24小时制);mm表示分钟数;ss表示秒的整数部分
,ff为秒的小数部分。如“9.1:40:58”表示9天、1小时、
40分钟和58秒。
C#从入门到实践
20.2.1
字段
TimeSpan结构包含以下8个静态字段,如MaxValue、MinValue
等,它们的具体说明如下。
 MaxValue字段,最大的TimeSpan值,它的值为
+10675199.02:48:05.4775807。
 MinValue字段,最小的TimeSpan值,它的值为10675199.02:48:05.4775808。
 Zero字段,零TimeSpan值,它的值为00:00:00。常常用于与
其他TimeSpan对象的比较。
 TicksPerDay字段,一天中的刻度数,它的值为8,640亿。
 TicksPerHour字段,1小时的刻度数,它的值为360亿。
 TicksPerMinute字段,1分钟的刻度数,它的值为6亿。
 TicksPerSecond字段,1秒钟的刻度数,它的值为1,000万。
 TicksPerMillisecond字段,1毫秒的刻度数,它的值为1万。
C#从入门到实践
20.2.2
属性
TimeSpan结构包含11个实例属性。通过这11个属性,可以获取
TimeSpan对象的天数、小时数、分钟数、秒数、毫秒数等。
TimeSpan结构的属性具体说明如表20.4所示。
属性
说明
Days
获取TimeSpan对象的整天数。
Hours
获取TimeSpan对象的整小时数。
Minutes
获取TimeSpan对象的整分钟数。
Seconds
获取TimeSpan对象的整秒数。
Milliseconds
获取TimeSpan对象的整毫秒数。
Ticks
获取TimeSpan对象的刻度数。
TotalDays
获取TimeSpan对象的天数的整数部分和小数部分。
TotalHours
获取TimeSpan对象的小时数的整数部分和小数部分。
TotalMinutes
获取TimeSpan对象的分钟数的整数部分和小数部分。
TotalSeconds
获取TimeSpan对象的秒数的整数部分和小数部分。
TotalMilliseconds
获取TimeSpan对象的毫秒数的整数部分和小数部分。
C#从入门到实践
20.2.3
方法
TimeSpan结构共包括个16方法,其中,静态方法10个,实例方法6
个。TimeSpan结构的静态方法具体说明如表20.5所示。
方法
说明
Compare()
比较两个TimeSpan值,它的返回值可以是0、-1或1。
Equals()
判断两个TimeSpan结构的实例是否相等。如果是,则返回true,否则返回false。
FromDays()
根据指定的天数,创建一个TimeSpan结构的实例。
FromHours()
根据指定的小时数,创建一个TimeSpan结构的实例。
FromMinutes()
根据指定的分钟数,创建一个TimeSpan结构的实例。
FromSeconds()
根据指定的秒数,创建一个TimeSpan结构的实例。
FromMilliseconds()
根据指定的毫秒数,创建一个TimeSpan结构的实例。
FromTicks()
根据指定的刻度数,创建一个TimeSpan结构的实例。
Parse()
将一个字符串转换为其相应的TimeSpan对象。
TryParse()
将一个字符串转换为其相应的TimeSpan对象。
C#从入门到实践
20.3
日期和时间的常用操作
DateTime结构是C#编程中最为常用的一个结构之一。日期
和时间的常用操作主要包括日期和时间的格式化、计算
日期和时间的差、追加日期和时间等。本小节将详细介
绍这些操作。
C#从入门到实践
20.3.1
格式化
日期和时间格式化是指将DateTime结构的实例转换为其相对应的
某一种字符串表示形式。DateTime结构提供了多个以“To”开头
的方法。这些方法可以将DateTime对象转换为不同格式的字符串
形式,常用的方法如表20.7所示。
方法
说明
ToString()
转换为其等效的字符串表示形式。
ToLongDateString() 转换为其等效的长日期字符串表示形式。
ToShortDateString() 转换为其等效的短日期字符串表示形式。
ToLongTimeString() 转换为其等效的长时间字符串表示形式。
ToShortTimeString() 转换为其等效的短时间字符串表示形式。
C#从入门到实践
20.3.2
计算时间差
计算时间差可以使用Subtract()方法。该方法可以计算两个
时间的差值,也可以计算时间和时间间隔的差值。它存
在以下两种重载形式。
 public TimeSpan Subtract(DateTime value),从当前实例
中减去指定的日期和时间,返回类型为TimeSpan。其中
,value参数表示被减去的日期和时间。
 public DateTime Subtract(TimeSpan value),从当前实例
中减去指定的时间间隔,返回类型为DateTime。其中,
value参数表示被减去的时间间隔。
C#从入门到实践
20.3.3
追加时间
追加时间是指将指定的时间或时间部分(如年份、月份、小时等
)追加到一个时间上,并计算出一个新的时间。DateTime结构提
供多个以“Add”开头的方法可以实现追加时间的功能,这些方法
的具体说明如表20.8所示。
方法
说明
Add()
将指定的TimeSpan的值加到指定的时间上。
AddYears()
将指定的年份数加到指定的时间上。
AddMonths()
将指定的月份数加到指定的时间上。
AddDays()
将指定的天数加到指定的时间上。
AddHours()
将指定的小时数加到指定的时间上。
AddMinutes()
将指定的分钟数加到指定的时间上。
AddSeconds()
将指定的秒数加到指定的时间上。
AddMilliseconds()
将指定的毫秒数加到指定的时间上。
AddTicks()
将指定的刻度数加到指定的时间上。
C#从入门到实践
20.4
实例一:计算for循环的运算时间
【实例20-1】计算for循环的运算时间。该功能由ConsumeTime()
方法实现。
C#从入门到实践
20.5
小结
本章主要介绍了C#语言中的日期和时间处理,如DateTime
结构、TimeSpan结构、格式化日期和时间、计算日期和
时间差、追加日期和时间等。其中,读者要着重掌握格
式化日期和时间,以及计算日期和时间差的方法,为后
续编写C#程序代码奠定基础。下一章将要介绍.NET
Framework中的的IO流、目录和文件处理。
C#从入门到实践
20.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_20”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)获取当前时间,并显示在控制台。
(3)计算一个for语句执行的时间。其中,该for语句执行
1000000次。
C#从入门到实践
第21章
IO流、目录和文件处理
IO流、目录和文件处理是系统最为常见的IO操作。IO流为
文件、输入/输出设备、内部进程通信管道、TCP/IP套接
字提供了操作方法。目录处理包括创建、删除、移动、
遍历目录等操作,文件处理包括创建、写入、读取、移
动、删除文件等操作。本章将讲解IO流、目录和文件处
理,主要介绍以下知识点。
 文件流;
 内存流;
 目录处理;
 文件处理。
C#从入门到实践
21.1
IO流
流是字节序列的抽象概念,如文件、输入/输出设备、内部
进程通信管道、TCP/IP套接字等。Stream类是所有流的
抽象基类,它可以为流提供一般性视图,从而使得开发
人员不需要了解IO设备的具体细节。与流相关的操作包
括以下3个基本操作。
 读取流,即读取流中的内容。
 写入流,即将指定的内容写入到流中。
 流支持查找,即可以查找或设置流的当前位置。
C#从入门到实践
21.1.1
文件流
FileStream(文件流)类公开以文件为主的Stream,它既支
持同步读写操作,也支持异步读写操作。使用文件流可
以对文件进行读取、写入、打开和关闭操作,以及系统
相关操作的标准输入、标准输出等。
FileStream类包括9个属性,它们可以描述FileStream类的实
例的特性,如流的长度(以字节为单位)、流的当前位
置、是否能够读或写或查询等。FileStream类的属性的具
体说明如表21.1所示。
C#从入门到实践
21.1.2
内存流
MemoryStream类可以用来创建其支持存储区为内存的流。
它可以封装内存中的存储的数据,这些数据的表现形式
为无符号字节数组。并且,通过MemoryStream类的实例
可以直接在内存中访问该数组。特别地,使用内存流可
以降低应用程序对临时缓冲区和临时文件的需要。
C#从入门到实践
21.2
目录处理
在.NET Framework中,用来处理目录的类主要包括
Directory和DirectoryInfo类。Directory类是一个静态类
,它公开用于创建、移动、枚举目录和子目录的静态方
法。DirectoryInfo类是一个密封类,从FileSystemInfo类
派生,并公开用于创建、移动、枚举目录和子目录的实
例方法。
C#从入门到实践
21.2.1
Directory类
Directory类是一个静态类,它只包含多个静态方法,用来创建、移
动、枚举目录和子目录。其中,常用的静态方法具体说明如表21.5
所示。
方法
说明
CreateDirectory()
创建指定路径的目录。
Delete()
删除指定的目录。
Exists()
判断指定路径的目录是否存在。如果存在,返回true,否则返回false。
Move()
将指定文件或目录及其内容移到新位置。
GetParent()
获取指定路径的父目录。
GetCurrentDirectory()
获取应用程序的当前工作目录。
SetCurrentDirectory()
设置应用程序的当前工作目录。
GetDirectories()
获取指定目录中子目录。
GetDirectoryRoot()
获取指定路径的卷信息或根信息。
GetFiles()
获取指定目录中的文件。
GetFileSystemEntries()
获取指定目录中所有文件和子目录。
GetLogicalDrives()
获取当前计算机上的逻辑驱动器。
GetCreationTime()
获取目录的创建日期和时间。
SetCreationTime()
设置指定的文件或目录的创建日期和时间。
GetLastAccessTime()
获取上次访问指定文件或目录的日期和时间。
SetLastAccessTime()
设置上次访问指定文件或目录的日期和时间。
GetLastWriteTime()
获取上次写入指定文件或目录的日期和时间。
SetLastWriteTime()
设置上次写入目录的日期和时间。
C#从入门到实践
21.2.2
DirectoryInfo类
DirectoryInfo类是一个密封类,它可以用来创建、移动、枚举目录
和子目录。DirectoryInfo类包括4个属性,可以用来获取目录的名
称、父目录等,具体说明如表21.6所示。
属性
说明
Exists
判断指定目录是否存在。如果存在,则返回true,否则返回false。
Name
获取目录的名称。
Parent
获取指定子目录的父目录。
Root
获取路径的根部分。
C#从入门到实践
21.2.3
创建目录
创建目录可以使用以下3种方法中的任何一种。
 Directory类的CreateDirectory()方法,用来创建一个目录
。
 DirectoryInfo类的Create()方法,用来创建一个目录。
 DirectoryInfo类的CreateSubdirectory()方法,用来创建
一个指定目录下的子目录。
C#从入门到实践
21.2.4
删除目录
删除目录可以使用以下2种方法中的任何一种。
 Directory类的Delete()方法,用来删除一个目录。
 DirectoryInfo类的Delete()方法,用来删除一个目录。
Directory类的Delete()方法存在以下两个原型。
 public static void Delete(string path),删除path指定的目
录,且该目录必须为空目录。
 public static void Delete(string path,bool recursive),删除
path指定的目录。recursive参数指定是否删除该目录下的
所有内容(如子目录、文件等)。
C#从入门到实践
21.2.5
移动目录
移动目录可以使用以下2种方法中的任何一种。
 Directory类的Move()方法,将指定文件或目录及其内容
移到新位置。
 DirectoryInfo类的MoveTo()方法,将指定目录及其内容
移到新位置。
C#从入门到实践
21.2.6
遍历目录
遍历目录是指获取该目录下的子目录或文件,主要存在一下
6种方法。
 Directory类的GetDirectories()方法,获取指定目录中子
目录。
 Directory类的GetFiles()方法,获取指定目录中的文件。
 Directory类的GetFileSystemEntries()方法,获取指定目
录中所有文件和子目录。
 DirectoryInfo类的GetDirectories()方法,获取当前目录的
子目录。
 DirectoryInfo类的GetFiles()方法,获取当前目录的文件
。
 DirectoryInfo类的GetFileSystemInfos()方法,获取当前目
录的所有文件和子目录。
C#从入门到实践
21.3
文件处理
在.NET Framework中,用来处理文件的类主要包括File和
FileInfo类。File类是一个静态类,它提供用于创建、复
制、删除、移动和打开文件的静态方法。FileInfo类是一
个密封类,从FileSystemInfo类派生,并提供创建、复制
、删除、移动和打开文件的实例方法。
C#从入门到实践
21.3.1
File类
File类是一个静态类,它只包含多个静态方法,用来创建、
复制、删除、移动和打开文件。
C#从入门到实践
21.3.2
FileInfo类
FileInfo类是一个密封类,它可以用来创建、复制、删除、移动和
打开文件的实例方法。FileInfo类包括6个属性,可以用来获取文
件的名称、完整路径等,具体说明如表21.9所示。
属性
说明
Directory
获取父目录。
DirectoryName
获取文件的完整路径。
IsReadOnly
获取或设置当前文件是否为只读。
Exists
指定当前文件是否存在。
Length
获取当前文件的大小(字节)。
Name
获取文件的名称。
C#从入门到实践
21.3.3
创建文件
创建文件可以使用File类的Create()方法或者FileInfo类的
Create()方法。
【示例21-18】使用FileInfo类的Create()方法创建一个名称
为“my.ini”的文件。
FileInfo fi = new FileInfo("my.ini");
fi.Create();
C#从入门到实践
21.3.4
写入文件
存在多种方法,可以将指定内容写入到文件,如File类的
OpenWrite()方法、FileInfo类的OpenWrite()方法等。
C#从入门到实践
21.3.5
读取文件
存在多种方法,可以从指定文件中读取内容,如File类的
OpenRead()方法、FileInfo类的OpenRead()方法等。
【示例21-20】使用FileInfo类的OpenRead()方法从my.ini文
件读取内容,并转换为一个字符串(保存为valuer),最
终,将valuer的内容显示在控制台。
C#从入门到实践
21.3.6
移动文件
移动文件可以使用以下2种方法中的任何一种。
 File类的Move()方法,将指定文件移到新位置。
 FileInfo类的MoveTo()方法,将指定文件移到新位置。
C#从入门到实践
21.3.7
删除文件
删除文件可以使用以下2种方法中的任何一种。
 File类的Delete()方法,将删除指定的文件。
 FileInfo类的Delete()方法,将删除指定的文件。
C#从入门到实践
21.4
实例:读取目录下指定类型的文件的内
容
【实例21-1】实现了读取指定目录下的、指定文件类型的、
所有文件的内容,并在控制台中显示读取的内容。
C#从入门到实践
21.5
小结
本章主要介绍了.NET Framework中的IO流、目录和文件处
理,如文件流、目录流、目录处理、文件处理等。其中
,读者要着重掌握目录处理和文件处理,为后续编写对
文件操作的C#应用程序代码奠定基础。下一章将要介绍
C#语言的Windows窗体编程。
C#从入门到实践
21.6
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_21”
的控制台应用程序,并实现以下功能。
(1)将名称为“class1.cs”的文件添加到该应用程序中。
(2)在class1.cs文件中是实现使用二进制方法对
“readme.txt”文件的读写方法。
C#从入门到实践
第22章
Windows窗体编程
Windows窗体应用程序是基于Microsoft Windows平台至上一种经
典的可视化应用程序,它特别适合于包含丰富图形用户界面的
应用程序。Windows窗体应用程序运行之后,往往会显示一个
或多个的Windows窗体,具有友好的交互功能。使用.NET
Framework和C#语言可以开发功能强大的Windows窗体应用程
序。本章节主要介绍以下知识点。
 Windows窗体应用程序概述;
 Windows窗体基本控件;
 MainForm.cs窗体设计;
 菜单和工具栏;
 容器;
 对话框;
 数据网格视图控件;
 运行Sample_22应用程序。
C#从入门到实践
22.1
Windows窗体应用程序概述
本节介绍使用Microsoft Visual Studio 2008集成开发环境(
IDE)创建Sample_22 Windows窗体应用程序的方法,以
及该Windows窗体应用程序的起始点(Program.cs文件)
、配置信息(AssemblyInfo.cs文件)等。
C#从入门到实践
22.1.1
创建Sample_22 Windows窗体应用程
序
依次选择“开始”|“所有程序”|“Microsoft Visual Studio
2008”|“Microsoft Visual Studio 2008”命令,打开“起始
页 - Microsoft Visual Studio”窗口。单击“最近项目”面
板中的“创建”下的“项目”链接,弹出“新建项目”
对话框,如图22.1所示。
C#从入门到实践
22.1.2
应用程序起始点
双击“解决方案资源管理器”面板中的“Program.cs”节点
,打开Program.cs文件。该文件为Sample_22 Windows窗
体应用程序提供主入口点。
C#从入门到实践
22.1.3
配置程序集信息
首先展开“解决方案资源管理器”面板中的“Properties”节
点,然后双击“AssemblyInfo.cs”节点打开
AssemblyInfo.cs文件。该文件用来配置Sample_22
Windows窗体应用程序的程序集信息。
C#从入门到实践
22.2
基本控件
本小节对Windows窗体的基本控件做一个简单介绍。这些基
本控件包括标签控件、图片框控件、文本框控件、富文
本框控件、按钮控件、单项按钮和复选框。
C#从入门到实践
22.2.1
标签控件
标签(Label)控件是最为简单的Windows窗体控件,它可
以用来显示不能编辑的文本或图像。标签控件不能接收
焦点,但是可以作为其他控件的访问键。
C#从入门到实践
22.2.2
图片框控件
图片框(PictureBox)控件可以用来显示位图、GIF、JPEG
、图元文件或图标格式的图形,它显示的图片由Image属
性指定,也可以由ImageLocation属性指定被显示图片的
地址(在显示指定的图片时,由Load()方法实现)。
C#从入门到实践
22.2.3
文本框和富文本框
文本框(TextBox)控件可以用来获取用户输入或显示文本
。文本框可以用来编辑文本,也可以以只读方式显示文
本。文本框通常显示为单行,但也可以显示多个行。通
过Text属性可以获取或设置文本框的输入或显示的文本
。
富文本框(RichTextBox)控件和文本框相比,它能够处理
有格式的文本,还可以显示字体、颜色、链接、嵌入的
图像等。实际上,富文本框能够提供类似字处理应用程
序的文本操作和显示功能,如复制、剪切、粘贴、全选
等。
C#从入门到实践
22.2.4
按钮控件
按钮(Button)控件允许用户通过单击来执行操作。每当用
户单击按钮时,即调用该按钮事先定义的Click事件处理
程序。按钮显示的文本可以通过其Text属性指定,另外
,按钮还可以使用Image或者ImageList属性显示图像。
C#从入门到实践
22.2.5
单项按钮和复选框
单项按钮由RadioButton类实现,可以为用户提供由两个或
多个互斥选项组成的选项集。多个单选框可以组合为一
个组。对于同一组内的所有单项按钮而言,用户一次只
能选中一个单项按钮。复选框由CheckBox类实现,它可
以用来指定某个条件是打开的还是关闭的,即常常用来
提供“是/否”或者“真/假”选项。多个复选框也可以组
合为一个组,用户可以选择该组中的一个或多个复选框
。
C#从入门到实践
22.3
MainForm.cs窗体设计
本小节介绍设计MainForm.cs窗体的方法,包括配置窗体的
属性(如名称、标题等)、添加控件(如标签控件、按
钮控件、图片框控件等)、创建新窗口(如等待对话框
等)等方法。
C#从入门到实践
22.3.1
配置窗体属性
打开“解决方案资源管理器”面板,并将
“Form1.cs”节点重命名为“MainForm.cs”
节点。双击该节点打开MainForm.cs窗体的
设计界面。单击MainForm.cs窗体,“属性
”面板将显示该窗体的各种属性及其值。
开发人员还可以通过“属性”面板配置该
窗体的各种属性。在此,笔者将
MainForm.cs窗体的Name属性的值设置为
“MainForm”、Text属性的值设置为
“Windows窗体编程”,如图22.3所示。
C#从入门到实践
22.3.2
添加控件
选择“工具箱”中的某一个控件,并直接拖放到
MainForm.cs窗体之上,就可以把该控件添加到
MainForm.cs窗体。在此,笔者向MainForm.cs窗体添加
了多个控件,并设置了相应的事件。
C#从入门到实践
22.3.3
创建等待对话框
下面介绍创建等待对话框(由WaittingForm.cs窗体实现)
的具体步骤。
C#从入门到实践
22.3.4
添加窗体事件
打开MainForm.cs窗体的设计界面,并双击该窗体就可以为
该窗体添加MainForm_Load(object sender, EventArgs e)
事件。当系统加载MainForm.cs窗体时,将触发该事件。
C#从入门到实践
22.4
菜单和工具栏
本小节介绍Windwos系统中最为熟悉的3个控件:菜单(由
MenuStrip类实现)、工具栏(由ToolStrip类实现)和上
下文菜单(由ContextMenuStrip类实现)的使用方法。
C#从入门到实践
22.4.1
菜单
菜单由MenuStrip类实现,它可以通过存放按照一般主题分
组的命令将功能公开给用户。使用菜单可以轻松实现以
下3个功能。
 创建支持高级用户界面和布局功能的易自定义的常用菜
单。
 支持操作系统的典型外观和行为。
 对所有容器和包含的项进行事件的一致性处理。
C#从入门到实践
22.4.2
工具栏
工具栏由ToolStrip类型实现,它可以为Windows窗体实现工
具栏的功能。并且,还可以向工具栏添加按钮、下拉按
钮、分割栏、文本框、下拉列表等控件。
C#从入门到实践
22.4.3
上下文菜单
上下文菜单由ContextMenuStrip类型实现。当用户单击鼠标
右键时,将在鼠标位置显示上下文菜单。如果要为某一
个窗体添加上下文菜单,只要将上下文菜单(ToolStrip
)控件从“工具箱”面板中直接拖放到窗体上即可。
C#从入门到实践
22.5
容器
本小节主要介绍Windwos系统中最为熟悉的3个容器控件:
面板(由Panel类实现)、组合框(由GroupBox类实现)
和选项卡(由TabControl和TabPage类实现)的使用方法
。
C#从入门到实践
22.5.1
面板
面板(Panel)控件是一个容器控件,可以用来包含其他控
件,即可以使用面板控件来组合控件的集合。默认情况
下,面板控件不显示任何边框。如果要显示边框,则需
要设置其BorderStyle属性的值。特别地,面板控件不显
示标题。面板控件包括以下3个常用属性。
 AutoSizeMode属性,指定控件的自动调整大小行为。
 BorderStyle属性,指定控件的边框样式。
 TabStop属性,指定用户能否使用Tab键将焦点放到该控
件上。
C#从入门到实践
22.5.2
组合框
组合框(GroupBox)控件和面板控件比较相似,也可以用在其他控件的
容器控件。它可以显示围绕一组具有可选标题的控件的框架,并且还
可以显示标题。组合框控件最典型的用途是用作一组单项按钮的容器
,并指定为以一个逻辑组,组内的单项按钮互相排斥。组合框控件包
括以下8个常用属性。
 AllowDrop属性,指定控件是否允许使用拖放操作和事件。
 AutoSize属性,指定控件是否根据其内容调整大小。
 AutoSizeMode属性,当控件启用AutoSize属性时,指定控件的行为方
式。
 DisplayRectangle属性,获取控件的维度的矩形。
 FlatStyle属性,获取或设置控件的平面样式外观。
 TabStop属性,指定用户能否使用Tab键将焦点放到该控件上。
 Text属性,控件的标题。
 UseCompatibleTextRendering属性,指定是否使用了兼容文本呈现控
件的标题。
C#从入门到实践
22.5.3
TabControl控件
TabControl控件可以显示多个选项卡,每一个选项卡都包含
一个选项卡页(TabPage)控件,而且每一个选项卡页可
以包含其他控件。单击每一个选项卡的标题可以设置它
的选项卡页为当前选项卡页。选项卡是TabControl控件
的一部分,但不是各个选项卡页的一部分。选项卡页控
件的属性只影响选项卡页的矩形工作区,而不影响选项
卡。TabControl控件包括以下3个常用属性。
 SelectedIndex属性,当前选定的选项卡页的索引。
 SelectedTab属性,当前选定的选项卡页。
 TabPages属性,TabControl控件中选项卡页的集合。
C#从入门到实践
22.5.4
容器窗体
容器窗体由ContainForm.cs窗体实现,介绍了面板、组合框
、选项卡等控件的使用方法。该窗体的标题为“容器”
,它包括1个TabControl控件、3个Tabpage、1个TextBox
控件、1个RichTextBox控件、1个PictureBox、1个
GroupBox、3个RadioButton和2个Panel控件。
C#从入门到实践
22.6
对话框
对话框(Dialog)是一种特殊的窗体(其FormBorderStyle
属性的值为FormBorderStyle.FixedDialog),常常用于与
用户交互和检索信息。本小节介绍Windows应用程序最
为常用的5种对话框:颜色对话框、字体对话框、打开文
件对话框、保存文件对话框和目录浏览对话框。
C#从入门到实践
22.6.1
对话框窗体
对话框窗体由DialogForm.cs窗体实现。用户单击该对话框
中的“设置颜色”、“设置字体”、“浏览文件…”、“
保存为…”和“浏览目录…”按钮分别弹出颜色对话框、
字体对话框、打开文件对话框、保存文件对话框和目录
浏览对话框。
C#从入门到实践
22.6.2
颜色对话框
颜色对话框由Windows窗体ColorDialog组件实现,它是一
个预先设置的对话框。用户可以从该对话框的调色板中
选择颜色,以及将自定义颜色添加到该调色板。如果开
发基于Windows的应用程序,开发人员可以使用该对话
框来实现选择颜色功能,而不需要再配置自己的对话框
。
颜色对话框包括7个常用属性,如获取颜色对话框中选择的
颜色的Color属性、禁用“定义自定义颜色”按钮的
AllowFullOpen属性等。
C#从入门到实践
22.6.3
字体对话框
字体对话框由Windows窗体ColorDialog组件实现,它也是一个预先
设置的对话框。用户可以从该对话框中选择系统上当前安装的字体
。通过该对话框,用户可以设置文本的字体、样式、大小、脚本和
效果。字体对话框包括5个常用属性,具体说明如表22.5所示。
属性
描述
Font
用户选定的字体。
Color
用户选定的字体颜色。
MaxSize
用户可选择的最大磅值。
MinSize
用户可选择的最小磅值。
ShowHelp
指示是否显示“帮助”按钮。
C#从入门到实践
22.6.4
打开文件对话框
打开文件对话框由Windows窗体OpenFileDialog组件实现,它与
Windows操作系统所公开的“打开文件”对话框相同。打开文件对
话框包括5个常用属性,具体说明如表22.6所示。
属性
描述
Multiselect
是否允许选择多个文件。
ReadOnlyChecked
是否选定只读复选框。
SafeFileName
所选文件的文件名和扩展名。
SafeFileNames
所有选定文件的文件名和扩展名的数组。
ShowReadOnly
是否包含只读复选框。
C#从入门到实践
22.6.5
保存文件对话框
保存文件对话框由Windows窗体SaveFileDialog组件实现,它与
Windows使用的标准“保存文件”对话框相同。保存文件对话
框包括2个常用属性,具体说明如表22.7所示。
属性
描述
CreatePrompt
如果用户指定不存在的文件,对话框是否提示用户允许
创建该文件。
OverwritePrompt
如果用户指定的文件名已存在,保存文件对话框是否显
示警告。
C#从入门到实践
22.6.6
目录浏览对话框
目录浏览对话框由Windows窗体FolderBrowserDialog组件实现,它
可以显示一个用于浏览和选择文件夹的模式对话框。用户可以从该
对话框中选择文件夹。目录浏览对话框包括4个常用属性,如获取用
户所选择文件夹的路径的SelectedPath属性、启用“新建文件夹”按
钮的ShowNewFolderButton属性等。这些常用属性的具体说明如表
22.8所示。
属性
描述
SelectedPath
用户选定的路径。
ShowNewFolderButton
指示是否显示“新建文件夹”按钮。
Description
对话框中在树视图控件上显示的说明文本。
RootFolder
从其开始浏览的根文件夹。
C#从入门到实践
22.7
数据网格视图控件
数据网格视图控件窗体由DGVForm.cs窗体实现,该窗体使
用DataGridView(数据网格视图)控件显示数据。
DGVForm.cs窗体的标题为“数据网格视图控件”,它只
包含1个DataGridView控件(Name属性的值为dgvData)
。
运行Sample_22 Windows窗体应用程序之后,单击“数据网
格视图”命令打开“数据网格视图控件”对话框(
DGVForm.cs窗体),如图22.26所示。
C#从入门到实践
22.8
运行应用程序
按下“F5”按钮或者单击Microsoft Visual Studio 2008集成开
发环境中的按钮即可运行Sample_22 Windows窗体应用程
序。该应用程序运行之后,显示的第一个窗口为
“Form1”窗口,如图22.27所示。
C#从入门到实践
22.9
小结
本章主要介绍了Windows窗体应用程序,如Windows窗体应
用程序概述、Windows窗体基本控件、MainForm.cs窗体
设计、菜单和工具栏、容器、对话框、数据网格视图控
件等。其中,读者要着重掌握Windows窗体基本控件、
菜单、工具栏、容器、对话框和数据网格视图控件的使
用方法,为后续编写功能强大的Windows应用程序奠定
基础。下一章将要介绍.NET Framework中的GDI+绘图
技术。
C#从入门到实践
22.10
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_22”
的Windows应用程序,并实现等待对话框的功能。
C#从入门到实践
第23章
使用GDI+绘图
GDI+是.NET Framework中专门用于绘制线条和形状、呈现
文本或显示与操作图像的技术。Graphics类封装一个
GDI+绘图图面,Graphics对象和点、区域、颜色、刷、
画笔、字体等结构或类提供将对象绘制到显示设备的方
法。本章节主要介绍以下知识点。
 Graphics类;
 点、区域、颜色、刷、画笔和字体;
 绘制直线、虚线和曲线;
 绘制多边形和椭圆;
 绘制饼状图;
 绘制文本。
C#从入门到实践
23.1
GDI+概述
GDI+是Windows XP操作系统中提供二维矢量图形、图像处
理和版式的部分。.NET Framework为操作图形提供了
GDI+应用程序编程接口,GDI+是 Windows图形设备接
口(GDI)的高级实现,通过使用GDI+,开发人员可以
创建图形、绘制文本,以及以对象的方式来操作图形或
图像。
C#从入门到实践
23.1.1
Graphics类
Graphics类封装一个GDI+绘图图面,提供将对象绘制到显
示设备的方法,是可以用来创建图形图像的对象。通常
,Graphics对象与特定的设备上下文关联。
1.创建Graphics对象
2.绘制图形、文本或图像
3.填充图形或图像
C#从入门到实践
23.1.2
点和区域
在GDI+中,二维图像都基于一个二维平面中,并使用点、
矩形、区域来描述这些图像。这个二维平面的坐标系如
图23.1所示。平面的左上角为坐标系的原点,水平朝右的
方向表示X轴的正方向,垂直朝下的方向表示Y轴的正方
向。
1.Point和PointF结构
2.Rectangle和RectangleF结构
3.Size和SizeF结构
4.Region类
C#从入门到实践
23.1.3
颜色
Color(颜色)结构表示一种ARGB颜色,它由4个分量值(
alpha、红色、绿色和蓝色)组成。Color结构包括多个方
法,如用来创建颜色的FromArgb()方法、
FromKnownColor()方法、FromName()方法等。
C#从入门到实践
23.1.4
刷
Brush(刷)类定义用于填充图形形状(如矩形、椭圆、饼
形、多边形和封闭路径)的内部的对象。
注意:Brush类是一个抽象基类,不能进行实例化。若要创
建一个刷的实例,必须使用从Brush派生出的类,如
SolidBrush、TextureBrush、LinearGradientBrush类等
。
C#从入门到实践
23.1.5
画笔
Pen(画笔)类定义用于绘制直线和曲线的对象,还可以指
定直线的宽度、样式等。要创建一个画笔可以使用Pen类
的构造函数。Pen类包括4个构造函数,具体说明如下。
 public Pen(Brush brush),使用刷创建画笔。brush参数
指定画笔所使用的刷。
 public Pen(Color color),使用颜色创建画笔。color参数
指定画笔所使用的颜色。
 public Pen(Brush brush,float width),使用刷创建画笔。
brush参数指定画笔所使用的刷,width参数指定画笔的
宽度。
 public Pen(Color color,float width),使用颜色创建画笔。
color参数指定画笔所使用的颜色,width参数指定画笔的
宽度。
C#从入门到实践
23.1.6
字体
Font(字体)类定义特定的文本格式,包括字体、字号和字
形属性。创建字体可以使用Font类的构造函数。
C#从入门到实践
23.2
实例一:使用GDI+绘制线条、形状和文
本
【实例23-1】使用GDI+中的Graphics对象对象在Panel控件
上绘制直线、折线、曲线、虚线、矩形、三角形、多边
形、椭圆、饼状图和文本。下面介绍具体实现方法。
C#从入门到实践
23.2.1
创建Sample_23窗体应用程序
【实例23-1】创建了名称为“Sample_23”的Windows Form
应用程序。
C#从入门到实践
23.2.2
Paint事件
当重绘Panel控件时,会触发Paint事件。该事件由Control类
(控件的基类)提供,Panel类继承该事件。在
Sample_23窗体应用程序中,笔者为pChart控件添加了
Paint事件,并在该事件中为pChart控件的顶部绘制了3D
边界。该事件的名称为pChart_Paint(object
sender,PaintEventArgs e)。
C#从入门到实践
23.2.3
绘制直线
单击MainForm窗体中的“绘制直线”按钮可以在pChart控
件中绘制一条直线。该功能由“绘制直线”按钮的Click
事件——btnDrawLine_Click(object sender,EventArgs e)
实现。
C#从入门到实践
23.2.4
绘制折线
单击MainForm窗体中的“绘制折线”按钮可以在pChart控
件中绘制一条折线。该功能由“绘制折线”按钮的Click
事件——btnDrawLines_Click(object sender,EventArgs e)
实现。
C#从入门到实践
23.2.5
绘制曲线
单击MainForm窗体中的“绘制曲线”按钮可以在pChart控
件中绘制一条曲线。该功能由“绘制曲线”按钮的Click
事件——btnDrawCurve_Click(object sender,EventArgs
e)实现。
C#从入门到实践
23.2.6
绘制虚线
单击MainForm窗体中的“绘制虚线”按钮可以在pChart控
件中绘制一条虚线。该功能由“绘制虚线”按钮的Click
事件——btnDrawDashLine_Click(object
sender,EventArgs e)实现。
C#从入门到实践
23.2.7
绘制矩形
单击MainForm窗体中的“绘制矩形”按钮可以在pChart控
件中绘制一个矩形。该功能由“绘制矩形”按钮的Click
事件——btnDrawRect_Click(object sender,EventArgs e)
实现。
C#从入门到实践
23.2.8
绘制三角形
单击MainForm窗体中的“绘制三角形”按钮可以在pChart
控件中绘制一个三角形。该功能由“绘制三角形”按钮
的Click事件——btnDrawTriangle_Click(object
sender,EventArgs e)实现。
C#从入门到实践
23.2.9
绘制多边形
单击MainForm窗体中的“绘制多边形”按钮可以在pChart
控件中绘制一个多边形。该功能由“绘制多边形”按钮
的Click事件——btnDrawPolygon_Click(object
sender,EventArgs e)实现。
C#从入门到实践
23.2.10
绘制椭圆
单击MainForm窗体中的“绘制椭圆”按钮可以在pChart控
件中绘制一个椭圆。该功能由“绘制椭圆”按钮的Click
事件——btnDrawEllipse_Click(object sender,EventArgs
e)实现。
C#从入门到实践
23.2.11
绘制饼状图
单击MainForm窗体中的“绘制饼状图”按钮可以在pChart
控件中绘制一个饼状图。该功能由“绘制饼状图”按钮
的Click事件——btnDrawPie_Click(object
sender,EventArgs e)实现。
C#从入门到实践
23.2.12
绘制文本
单击MainForm窗体中的“绘制文本”按钮可以在pChart控
件中绘制一段文本“这是一段文本。”。该功能由“绘
制文本”按钮的Click事件——
btnDrawString_Click(object sender,EventArgs e)实现。
C#从入门到实践
23.3
小结
本章主要介绍了NET Framework中的GDI+绘制技术,如
Graphics类、区域、颜色、刷、画笔、字体等,以及绘
制直线、虚线、曲线、多边形、椭圆、饼状图和文本。
其中,读者要着重掌握使用GDI+绘制直线、虚线、曲线
、多边形、椭圆、饼状图和文本的方法,为后续编写功
能强大的Windows应用程序奠定基础。下一章将要介绍
.NET Framework中的数据访问。
C#从入门到实践
23.4
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_23”
的控制台应用程序,并实现以下功能。
(1)创建名称为“MyForm.cs”的窗体。
(2)在在名称为“MyForm.cs”窗体上绘制以下图形。
直线;
折线;
曲线;
虚线;
矩形;
三角形;
多边形;
椭圆;
圆;
扇形;
饼状图;
文本。
C#从入门到实践
第24章
.NET数据访问
.NET数据访问是.NET Framework中很重要的一个功能,它
由ADO.NET实现。通过ADO.NET,开发人员可以访问
Microsoft SQL Server、ODBC、Oracle、OLE DB、
XML等数据源,并检索、操作和更新这些数据源中的数
据。本章节主要介绍以下知识点。
 ADO.NET组成结构;
 ADO.NET基本对象,如SqlCommand、SqlDataReader、
SqlDataAdpater、DataSet等对象;
 使用ADO.NET操作SQL Server数据库,包括连接、读取
、插入、修改、删除等操作;
 使用DataGridView控件显示数据;
 使用ListView控件显示数据;
 使用TreeView控件显示数据。
C#从入门到实践
24.1
ADO.NET概述
ADO.NET是.NET Framework中提供了专门用来处理数据的
技术。通过该技术,开发人员可以访问SQL Server、
ODBC、Oracle、OLE DB、XML等数据源,并检索、操
作和更新这些数据源中的数据。
C#从入门到实践
24.1.1
ADO.NET组成结构
ADO.NET是.NET Framework中的一部分,它提供对
Microsoft SQL Server、ODBC、Oracle等数据源,以及
通过OLE DB和XML公开的数据源的一致访问。应用程
序(Windows Form、ASP.NET等)可以使用ADO.NET
来连接到这些数据源,并检索、操作和更新其中的数据
。ADO.NET组成结构如图24.1所示。
1..NET Framework数据提供程序
2.DataSet(数据集)
DataSet
.NET Framework数据提供程序
Connection
DataAdapter
事务
DataTableCollection
SelectCommand
数据表
DataRowCollection
Command
Insertommand
参数
UpdateCommand
DataReader
DataColumnCollection
ConstraintCollection
DeleteCommand
DataRelationCollection
XML
数据库
C#从入门到实践
24.1.2
ADO.NET基本对象
ADO.NET基本对象主要包括Connection、Command、
DataReader、DataAdapter、DataSet、DataView等对象
。本小节只介绍用于操作SQL Server数据库相关的
SqlConnection、SqlCommand、SqlDataReader、
SqlDataAdapter、DataSet、DataView等。
1.SqlConnection对象
2.SqlCommand对象
3.SqlDataReader对象
4.DataSet对象
C#从入门到实践
24.2
实例一:操作SQL Server数据库
【实例24-1】使用ADO.NET实现了操作SQL Server 2005数
据库的功能,包括连接数据库、读取数据、插入数据、
修改数据、删除数据、使用DataGirdView控件显示数据
、使用ListView控件显示数据和使用TreeView控件显示
数据。
C#从入门到实践
24.2.1
创建Sample_24窗体应用程序
【实例24-1】创建了名称为“Sample_24”的Windows Form
应用程序。
C#从入门到实践
24.2.2
创建CSharp3DB数据库
Sample_24 Windows Form应用程序连接了名称为
“CSharp3DB”的SQL Server 2005数据库,并操作了该
数据库中的数据。
C#从入门到实践
24.2.3
连接数据库
单击MainForm窗体中的“连接数据库”按钮可以连接
CSharp3DB数据库。该功能由“连接数据库”按钮的
Click事件——btnConnect_Click(object sender,EventArgs
e)实现。
C#从入门到实践
24.2.4
读取数据
单击MainForm窗体中的“读取数据”按钮可以读取
CSharp3DB数据库的Data表中的所有数据,并显示在
rtbMessage控件中。该功能由“读取数据”按钮的Click
事件——btnReadData_Click(object sender,EventArgs e)
实现。
C#从入门到实践
24.2.5
插入数据
单击MainForm窗体中的“插入数据”按钮可以向
CSharp3DB数据库的Data表中插入新的数据。该功能由
“插入数据”按钮的Click事件——
btnInsertData_Click(object sender,EventArgs e)实现。
C#从入门到实践
24.2.6
修改数据
单击MainForm窗体中的“修改数据”按钮可以修改
CSharp3DB数据库的Data表中的数据。该功能由“修改
数据”按钮的Click事件——btnUpdateData_Click(object
sender,EventArgs e)实现。
C#从入门到实践
24.2.7
删除数据
单击MainForm窗体中的“删除数据”按钮可以删除
CSharp3DB数据库的Data表中的数据。该功能由“删除
数据”按钮的Click事件——btnDeleteData_Click(object
sender,EventArgs e)实现。
C#从入门到实践
24.2.8
使用DataGridView控件显示数据
单击MainForm窗体中的“显示数据”按钮可以在
DataGridView控件中显示CSharp3DB数据库的Data表中
的数据。该功能由ShowDataWithDataGirdView()方法实
现。
C#从入门到实践
24.2.9
使用ListView控件显示数据
单击MainForm窗体中的“显示数据”按钮可以在ListView
控件中显示CSharp3DB数据库的Data表中的数据。该功
能由ShowDataWithListView()方法实现。
C#从入门到实践
24.2.10
使用TreeView控件显示数据
单击MainForm窗体中的“显示”按钮可以在TreeView控件
中显示CSharp3DB数据库的Data表中的数据。该功能由
ShowDataWithTreeView()方法实现。
C#从入门到实践
24.3
小结
本章主要介绍了.NET Framework中中的数据访问功能,如
ADO.NET组成结构、ADO.NET基本对象、使用
ADO.NET操作SQL Server数据库、使用DataGridView控
件显示数据、使用ListView控件显示数据、使用
TreeView控件显示数据等。其中,读者要着重掌握
ADO.NET基本对象,以及使用ADO.NET操作SQL
Server数据库的方法,为后续编写功能强大的、处理数据
(特别是处理数据库中的数据)的C#程序代码奠定基础
。下一章将要介绍使用C#语言开发图书管理系统的方法
。
C#从入门到实践
24.4
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_24”
的Windows应用程序,并实现以下功能。
(1)将名称为“Form1.cs”的窗体添加到该应用程序中。
(2)使用Form1.cs窗体实现用户管理功能(包括查询、添
加、修改和删除用户)。其中,用户表User保存在名称
为“UserDB”的SQL Server 2005数据库中,且该表包含3
个列:ID、Username和Password。
C#从入门到实践
第25章
图书管理系统
图书管理系统是当前最为流行的管理系统之一,它一般包括
登录、主窗口、图书分类管理、书籍管理、借阅书籍、
归还书籍、浏览书籍等功能。本章将讲解使用Visual
Studio 2008开发图书管理系统(应用程序的名称为
“LibraryManager”,数据库的名称为
“LibraryManagerDB”,数据库版本为SQL Server 2005
)的方法,主要介绍以下知识点。
 系统总体设计,包括功能设计、操作流程图、数据库设
计等。
 管理功能模块实现,包括管理员登录、主窗口、分类管
理、书籍管理、借阅书籍等功能。
 学生或教师功能模块实现,包括学生或教师登录、主窗
口、归还书籍、浏览书籍等功能。
C#从入门到实践
25.1
系统总体设计
本小节介绍图书管理系统——LibraryManager应用程序的
总体设计,主要包括系统功能设计、操作流程图设计、
图书管理系统应用程序的组成、LibraryManagerDB数据
库设计、数据库实体类设计、应用程序主入口、应用程
序全局变量等。
C#从入门到实践
25.1.1
系统功能设计
图书管理系统可以分为两部分:管理员功能模块和学生或老
师功能模块。管理员功能模块为管理员提供服务,它提
供的功能如下,操作流程如图25.1所示。
返回
返回
分类管理
单击【分类管理】图标
借阅书籍
单击【借阅书籍】按钮
管理员登录
登录
主窗口
查看借阅人
单击借阅数量中的链接
删除书籍
单击【删除】链接
书籍管理
单击【添加书籍】按钮/【更新】链接
返回
关闭
C#从入门到实践
25.1.2
图书管理系统组成
图书管理系统应用程序的名称为
“LibraryManager”。在Visual
Studio 2008的“解决方案资源管理
器”面板中查看LibraryManager应
用程序,如图25.3所示。
LibraryManager应用程序的组成元
素说明如下。
C#从入门到实践
25.1.3
数据库设计
图书管理系统使用名称为“LibraryManagerDB”的
Microsoft SQL Server 2005数据库,它包括6个表:
Category、Group、User、Book、BookCategory和
UserBook表。
1.Category表
2.Group表
3.User表
4.Book表
5.BookCategory表
6.UserBook表
C#从入门到实践
25.1.4
数据库实体类设计
图书管理系统为LibraryManagerDB数据库创建名称为
“LibraryManagerDB.dbml”的DBML文件,并把
LibraryManagerDB数据库所有的表(Category、Group
、User、Book、BookCategory和UserBook表)添加到该
文件中,如图25.4所示。
C#从入门到实践
25.1.5
应用程序主入口
应用程序主入口的程序代码位于Program.cs文件(保存在
LibraryManage目录下)中。该文件定义名称为Program
的静态类和static void Main()静态方法。该静态方法调用
Application类的Run()静态方法运行第一个窗口——登录
窗体(即LoginForm类的实例)
C#从入门到实践
25.1.6
应用程序全局变量
图书管理系统在LibrarySystem.cs文件中创建了
LibrarySystem类,并定义了一个全局的、静态的变量
UserID。该变量用来保存登录用户的ID值。
C#从入门到实践
25.2
管理员模块实现
管理员功能模块共包括登录、主窗口、分类管理、书籍管理
、借阅书籍、查看借阅人等功能。管理员都能够通过主
窗口查看和浏览所有书籍,以及书籍的借阅情况;借阅
书籍窗口可以实现借阅书籍的功能,查看借阅人窗口可
以查看某一个书籍的所有借阅人的信息。本小节介绍这
些功能模块木咛迨迪帧
C#从入门到实践
25.2.1
管理员登录
管理员登录功能由LoginForm.cs窗体(保存在
LibraryManager目录下)实现。管理员可以输入用户名
和密码,单击“登录”按钮实现登录功能,单击“取消
”按钮关闭该窗口。
C#从入门到实践
25.2.2
主窗口
管理员主窗口由MainForm.cs窗体(保存在LibraryManager
目录下)实现。该窗口以列表形式显示指定分类下的书
籍;管理员单击“分类管理”图标打开分类管理的窗口
,单击“添加新书籍”按钮可以打开书籍管理窗口,单
击“借阅书籍”按钮打开借阅书籍的窗口。
C#从入门到实践
25.2.3
分类管理
分类管理功能由
CategoryForm.cs窗体(保
存在
LibraryManager/Admin目
录下)实现。管理员可以
创建和维护书籍的分类树
,如添加新的分类、修改
分类名称、删除分类等。
C#从入门到实践
25.2.4
书籍管理
书籍管理功能由BookForm.cs窗体(保存在
LibraryManager/Admin目录下)实现。管理员可以输入
用户名和密码,单击“登录”按钮实现登录功能,单击
“取消”按钮关闭该窗口。
C#从入门到实践
25.2.5
借阅书籍
借阅书籍功能由LendForm.cs窗体(保存在LibraryManager
目录下)实现。该窗体实现借阅指定书籍给指定用户的
功能。管理员可以选择借阅书籍的用户。
C#从入门到实践
25.2.6
查看借阅人
查看借阅人功能由LendUserInfoForm.cs窗体(保存在
LibraryManager目录下)实现。该窗口可以以列表方式
显示指定书籍的所有借阅人的信息。
C#从入门到实践
25.3
学生和老师功能模块实现
学生和老师功能模块共包括登录、主窗口、归还书籍、查看
书籍信息、浏览书籍、借阅书籍等功能。学生和老师都
能够通过主窗口查看其所借阅的书籍,并能够归还书籍
;浏览书籍窗口可以根据书籍分类浏览各种书籍,并借
阅书籍。本小节介绍这些功能模块的具体实现。
C#从入门到实践
25.3.1
学生或老师登录
学生或老师登录功能也是由LoginForm.cs窗体(保存在
LibraryManager目录下)实现。学生或老师也可以输入
用户名和密码,单击“登录”按钮实现登录功能,单击
“取消”按钮关闭该窗口。由于已经在25.2.1小节介绍了
该窗体的实现,因此,在此不做详细介绍。
C#从入门到实践
25.3.2
主窗口
学生和老师角色的主窗口都为由UserForm.cs窗体(保存在
LibraryManager目录下)实现。该窗口以列表形式显示
学生或老师已借的所有书籍;学生或老师单击“归还书
籍”按钮可以归还选择的书籍;单击“浏览书籍”按钮
可以打开浏览书籍的窗口。
C#从入门到实践
25.3.3
归还书籍
当用户单击UserForm.cs窗体中的“归还书籍”按钮(
btnReturn控件)触发Click事件——
btnReturn_Click(object sender, EventArgs e)。该事件实
现归还书籍的功能。
C#从入门到实践
25.3.4
查看书籍信息
查看书籍信息功能由
BookInfoForm.cs窗体(保存
在LibraryManager目录下)
实现。该窗口可以显示指定书
籍的详细信息,如名称、作者
、ISBN、出版单位、出版时
间、数量、状态、电子文档、
封面图片、图书简介、图书分
类等。
C#从入门到实践
25.3.5
浏览书籍
浏览书籍功能由BrowserForm.cs窗体(保存在
LibraryManager目录下)实现。该窗口根据分类、以列
表形式显示书籍信息,单击“借阅”链接可以借阅当前
行表示的书籍。
C#从入门到实践
25.3.6
借阅书籍
当用户单击“浏览书籍”窗口(BrowserForm.cs窗体)中每
一行中的“借阅”链接时,可以实现借阅该行表示的书
籍。该功能的实现方式和25.2.5小节中借阅书籍功能相似
,因此,在此不做详细介绍。
C#从入门到实践
25.4
小结
本章主要介绍了使用C#语言在Visual Studio 2008集成开发
环境中开发图书管理系统的方法,主要包括功能设计、
操作流程图、数据库设计,以及管理员登录、主窗口、
分类管理、书籍管理、借阅书籍、学生或教师登录、主
窗口、归还书籍、浏览书籍等功能的开发方法。其中,
读者要着重掌握使用Windows窗体编程的方法,为后续
编功能强大的Windows应用程序奠定基础。下一章将要
介绍P2P(点对点)聊天程序。
C#从入门到实践
25.5
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_25”
的Windows应用程序,并在该应用程序中实现用户管理
功能。
C#从入门到实践
第26章
P2P聊天工具
P2P聊天工具是当前最为流行的点对点的聊天工具,它一般
包括聊天工具的服务器、聊天工具的客户端等功能模块
。本章将讲解使用Visual Studio 2008集成开发环境开发
P2P聊天工具(名称为“P2PTalk”)的方法,主要介绍
以下知识点。
系统总体设计,包括功能设计、P2P聊天工具组成等;
 P2P聊天工具类库实现;
 P2P聊天工具服务器聊天窗口实现;
 P2P聊天工具客户端聊天窗体实现。
C#从入门到实践
26.1
系统总体设计
本小节介绍P2P聊天工具——P2PTalk项目的总体设计,主
要包括系统功能设计、P2P聊天工具的组成等。
C#从入门到实践
26.1.1
系统功能设计
P2P聊天工具可以分为两部分:P2P聊天工具客户端部分功
能模块和P2P聊天工具服务器端部分功能模块。P2P聊天
工具的客户端部分和服务器端部分功能模块都实现相同
的功能,具体描述如下。
 连接服务器,连接到指定的聊天服务器。
 断开服务器的连接,断开已经连接的聊天服务器。
 退出聊天,退出聊天状态,并释放占有的资源。
 发送聊天消息,可以将消息发送到服务器。
C#从入门到实践
26.1.2
P2P聊天工具组成
P2P聊天工具项目的名称为“P2PTalk”。在Visual Studio
2008的“解决方案资源管理器”面板中查看P2PTalk项目
,如图26.1所示。P2PTalk项目包括3个应用程序,具体
说明如下。
 Client应用程序,P2P聊天工具的客户端应用程序。
 P2PTalkLibrary类库,P2P聊天工具的类库,封装了实现
聊天功能的类。
 Server应用程序,P2P聊天工具的服务器端应用程序。
C#从入门到实践
26.2
P2P聊天工具类库实现
P2P聊天工具类库由P2PTalkLibrary项目实现,该项目的类
型为C#类库。如果生成该项目成功,将创建一个名称为
“P2PTalkLibrary.dll”的动态链接库文件(保存在该项
目的bin目录下)。
P2PTalkLibrary项目包括两个类文件:P2P.cs和Tool.cs,它
们分别包含P2P类和Tool类。下面将详细介绍这两个类的
功能。
C#从入门到实践
26.2.1
Tool类
Tool类被包含在P2PTalk.Component命名空间中,并引用了
2个命名空间:System.Net和System.IO。
C#从入门到实践
26.2.2
P2P类
P2P类被包含在P2PTalk.Component命名空间中,并引用了
2个命名空间:System.Net和System.IO。
C#从入门到实践
26.3
P2P聊天工具服务器聊天窗口
P2P聊天工具服务器由Server项目实现,P2P聊天工具服务
器聊天窗口由该项目下的MainForm.cs窗体(保存在
P2PTalk目录下)实现。用户可以通过该窗口连接服务器
,并和其他用户进行聊天。用户单击“连接”按钮可以
连接到指定的服务器,单击“断开”按钮可以断开服务
器的连接,单击“退出”按钮可以结束当前聊天状态,
单击“发送”按钮可以将详细发送给其他在线用户。
C#从入门到实践
26.4
P2P聊天工具客户端聊天窗口
由于P2P聊天工具客户端聊天窗口和P2P聊天工具服务器聊
天窗口功能上非常相似,实现方法也比较相似。因此,
在此不做详细介绍。
C#从入门到实践
26.5
小结
本章主要介绍了使用C#语言在Visual Studio 2008集成开发
环境中开发P2P聊天工具的方法,主要包括功能设计、
P2P聊天工具组成,以及P2P聊天工具类库、P2P聊天工
具服务器聊天窗口、P2P聊天工具客户端聊天窗体等功能
的开发方法。其中,读者要着重掌握P2P聊天工具类库和
P2P聊天工具客户端聊天窗体的方法,为后续编功能强大
的网络应用程序奠定基础。下一章将要介绍使用
ASP.NET技术(C#)开发校内网的方法。
C#从入门到实践
26.6
习题
在Server应用程序(26.3小节)中添加用户管理功能,并实
现可以将指定的消息仅仅发送的指定的某一个用户个功
能。
C#从入门到实践
第27章
我的校内网
校内网是当前最为流行的交流网站之一,它一般包括登录、
主页面、好友、相册、日志、聊天等功能。本章将讲解
使用Visual Studio 2008集成开发环境开发校内网网站(
名称为“MyXiaonei”,数据库的名称为“XiaoneiDB”,
数据库版本为SQL Server 2005)的方法,主要介绍以下
知识点。
 系统总体设计,包括功能设计、数据库设计等。
 常用功能模块实现,包括登录、主页面、好友、相册、
日志等功能。
C#从入门到实践
27.1
系统总体设计
本小节介绍校内网——MyXiaonei网站的总体设计,主要包
括系统功能设计、MyXiaonei网站的组成、XiaoneiDB数
据库设计、数据库实体类设计、标题模块、网站配置等
。
C#从入门到实践
27.1.1
系统功能设计
校内网网站比较复杂,在此,仅仅介绍常用的功能,主要包
括登录、好友(浏览好友、添加好友等)、相册(浏览
照片、上传照片等)、日志等功能,具体描述如下。
 用户登录,验证用户的身份是否合法。
 主页面,校内网网站的主页面。
 我的好友,按照分类方式浏览好友。
 添加好友,可以查询用户,并添加为好友。
 我的相册,按照分类方式浏览照片。
 上传照片,上传照片到服务器,并指定相应的分类。
 我的日志,按照分类方式浏览日志。
 添加日志,将新的日志添加到指定的分类下。
C#从入门到实践
27.1.2
校内网组成
校内网网站的名称为“MyXiaonei”。在Visual Studio 2008
的“解决方案资源管理器”面板中查看MyXiaonei网站,
如图27.1所示。
C#从入门到实践
27.1.3
数据库设计
校内网网站使用名称为“XiaoneiDB”的Microsoft SQL
Server 2005数据库,它包括6个表:Category、Group、
User、Book、BookCategory和UserBook表。
1.User表
2.Category表
3.Friend表
4.Log表
5.Photo表
C#从入门到实践
27.1.4
数据库实体类设计
校内网网站为XiaoneiDB数据库创建名称为
“XiaoneiDB.dbml”的DBML文件,并把XiaoneiDB数据
库所有的表(User、Category、Friend、Log和Photo表
)添加到该文件中,如图27.2所示。
C#从入门到实践
27.1.5
标题模块
标题模块由TitleUC.ascx用户控件实现,它将用来显示标题
。
C#从入门到实践
27.1.6
配置文件Web.config
MyXiaonei网站的连接字符串放置在Web.config配置文件的
<connectionString>元素中
C#从入门到实践
27.2
常用功能模块实现
校内网网站的常用功能模块主要包括登录、好友(浏览好友
、添加好友等)、相册(浏览照片、上传照片等)、日
志等功能。本小节将介绍这些功能的具体实现方法。
C#从入门到实践
27.2.1
登录页面
登录功能由Default.aspx页面实现,Default.aspx.cs文件为它
的代码隐藏文件。该页面提供了输入用户名和密码的文
本框,并实现用户登录的功能。Default.aspx页面的效果
图如图27.3所示。
1.界面设计
2.事件设计
C#从入门到实践
27.2.2
主页面
校内网主页面由Main.aspx和LeftTree.aspx页面共同实现。
Main.aspx页面使用了框架,并放置了两个<frame>元素
,它们的name属性的值分别为:Left和Desktop。其中,
Left框架放置LeftTree.aspx页面,Desktop框架默认放置
MyFriend.aspx页面。
C#从入门到实践
27.2.3
我的好友
我的好友由MyFriend.aspx页面实现,MyFriend.aspx.cs文件
为它的代码隐藏文件。该页面按照系统默认的分类显示
当前登录用户的好友。MyFriend.aspx页面的效果图如图
27.4所示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.2.4
添加好友
添加好友由AddFriend.aspx页面实现,AddFriend.aspx.cs文
件为它的代码隐藏文件。该页面为考生提供选择考试科
目的功能,并显示用户名称和考试时间。AddFriend.aspx
页面的效果图如图27.5所示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.2.5
我的相册
我的相册由MyPhoto.aspx页面实现,MyPhoto.aspx.cs文件
为它的代码隐藏文件。该页面按照系统默认的分类显示
当前登录用户的照片。MyPhoto.aspx页面的效果图如图
27.6所示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.2.6
上传照片
上传照片由UploadPhoto.aspx页面实现,
UploadPhoto.aspx.cs文件为它的代码隐藏文件。该页面为
用户提供上传照片的功能。其中,照片的文件保存到硬
盘,照片的信息保存到数据库。UploadPhoto.aspx页面的
效果图如图27.7所示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.2.7
我的日志
我的日志由MyLog.aspx页面实现,MyLog.aspx.cs文件为它
的代码隐藏文件。该页面按照系统默认的分类显示当前
登录用户的日志。MyLog.aspx页面的效果图如图27.8所
示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.2.8
添加日志
添加日志由AddLog.aspx页面实现,AddLog.aspx.cs文件为
它的代码隐藏文件。该页面为考生提供输入日志标题和
内容,并提交到数据库的功能。AddLog.aspx页面的效果
图如图27.9所示。
1.界面设计
2.初始化
3.事件设计
C#从入门到实践
27.3
小结
本章主要介绍了使用C#语言在Visual Studio 2008集成开发
环境中开发校内网的方法,主要包括统总体设计,包括
功能设计、数据库设计,以及登录、主页面、好友、相
册、日志、聊天等功能的开发方法。其中,读者要着重
掌握使用Web窗体编程的方法,为后续编功能强大的
ASP.NET网站奠定基础。
C#从入门到实践
27.4
习题
在Visual Studio 2008集成开发环境中创建名称为“Test_27”
的ASP.NET网站,并在该网站中实现用户管理功能。
C#从入门到实践
C#从入门到实践