欢迎光临
免费的PDF电子书下载网站

.NET应用程序开发技术与项目实践(C#版) PDF下载

编辑推荐

1、适应市场需求,内容实用。全书以企业对.NET开发人员要求的知识和技能来精心选择内容,由浅入深地介绍了.NET开发人员必备的C#程序设计基本知识和技能,突出重点,注重实用。2、按照“教学做”一体化设计教学单元,符合学习者的认知规律,能够有效提高读者的学习兴趣,培养读者自主学习和探究能力。3、以实际项目为载体,注重案例的实用性,将实例融入到知识讲解中,使知识和实例相辅相成,既有利于读者学习知识,又能为读者实际项目开发提供实践指导。4、配套资源丰富。本书提供完备的教学课件、教学设计以及所有实例的源代码以方便读者使用。有需要的读者可以到清华大学出版社网站下载或者与作者联系。

 ;

内容简介

C#语言是目前Windows平台下开发应用程序的主流语言之一,应用领域非常广泛,目前已成为ECMA(国际信息和通信系统标准化组织)与ISO标准规范。本书主要以Visual Studio 2013和SQL Server 2008作为开发工具,以工作过程为导向,围绕学生成绩管理系统开发来组织内容,实现了项目开发和理论知识的有机融合,由浅入深地介绍了利用C#开发应用程序的相关技术。 全书共13章。第1~3章以开发基于控制台的学生成绩管理系统为主线,深入讨论了C#程序的结构、数据类型和表达式、程序流程控制以及数组、字符串和集合等内容。第4章围绕改进的控制台学生成绩管理系统的开发,介绍了C#面向对象程序设计的核心技术和知识,包括类、继承性、多态性和接口、委托和事件等。第5~10章围绕基于WinForm的学生成绩管理系统的开发,全面介绍了Windows应用程序开发、数据库应用开发、文件与数据流技术、图形图像处理等核心技术。学完这一部分后,读者即可开发出一个功能较为完备的学生管理系统。第11~12章介绍了多线程和网络编程以及WPF程序开发技术。第13章给出了基于三层架构的学生成绩管理系统的完整设计与实现以及部署。通过这样由点到面的介绍,读者既可以学习C#程序设计的理论知识,又能运用所介绍的知识来解决实际问题,提高项目开发能力。 本书内容全面新颖,结构安排合理,案例丰富实用,有些案例可以直接应用到项目开发中。本书可以作为高等学校计算机及其相关专业的教材,也可以作为相关培训机构和软件开发人员的参考用书。

作者简介

暂无

.NET应用程序开发技术与项目实践(C#版) PDF下载

目录

目录

 ;

第1章.NET平台和C#语言

 ;

1.1.NET软件开发工具与环境

 ;

1.1.1任务描述: 建立.NET软件开发环境

 ;

1.1.2任务实现

 ;

1.1.3知识链接

 ;

1.1.4拓展与提高

 ;

1.2欢迎进入C#编程世界

 ;

1.2.1任务描述: 设计学生成绩管理系统V0.8启动界面

 ;

1.2.2任务实现

 ;

1.2.3知识链接

 ;

1.2.4拓展与提高

 ;

1.3知识点提炼

 ;

第2章C#程序开发基础

 ;

2.1变量和表达式

 ;

2.1.1任务描述: 学生信息输入

 ;

2.1.2任务实现

 ;

2.1.3知识链接

 ;

2.1.4拓展与提高

 ;

2.2智能决策——选择结构

 ;

2.2.1任务描述: 用户登录验证

 ;

2.2.2任务实现

 ;

2.2.3知识链接

 ;

2.2.4拓展与提高

 ;

2.3重复迭代——循环结构

 ;

2.3.1任务描述: 多个学生信息输入

 ;

2.3.2任务实现

 ;

2.3.3知识链接

 ;

2.3.4拓展与提高

 ;

2.4程序调试与异常处理

 ;

2.4.1任务描述: 用户登录模块的调试

 ;

2.4.2任务实现

 ;

2.4.3知识链接

 ;

2.4.4拓展与提高

 ;

2.5知识点提炼

 ;

第3章数组、字符串和集合

 ;

3.1数组

 ;

3.1.1任务描述: 学生信息输入和输出

 ;

3.1.2任务实现

 ;

3.1.3知识链接

 ;

3.1.4拓展与提高

 ;

3.2字符串处理

 ;

3.2.1任务描述: 学生信息输入和输出

 ;

3.2.2任务实现

 ;

3.2.3知识链接

 ;

3.2.4拓展与提高

 ;

3.3集合

 ;

3.3.1任务描述: 学生信息存储

 ;

3.3.2任务实现

 ;

3.3.3知识链接

 ;

3.3.4拓展与提高

 ;

3.4知识点提炼

 ;

第4章C#面向对象程序编程

 ;

4.1类和对象

 ;

4.1.1任务描述: 建立学生对象

 ;

4.1.2任务实现

 ;

4.1.3知识链接

 ;

4.1.4拓展与提高

 ;

4.2定义类成员

 ;

4.2.1任务描述: 学生对象的完善

 ;

4.2.2任务实现

 ;

4.2.3知识链接

 ;

4.2.4拓展与提高

 ;

4.3继承性、多态性和接口

 ;

4.3.1任务描述: 简单工资管理系统

 ;

4.3.2任务实现

 ;

4.3.3知识链接

 ;

4.3.4拓展与提高

 ;

4.4委托和事件

 ;

4.4.1任务描述: ; 对象数组的排序

 ;

4.4.2任务实现

 ;

4.4.3知识链接

 ;

4.4.4拓展与提高

 ;

4.5知识点提炼

 ;

第5章Windows应用程序开发基础

 ;

5.1Windows应用程序基本结构

 ;

5.1.1任务描述: 学生成绩管理系统主窗体的设计

 ;

5.1.2任务实现

 ;

5.1.3知识链接

 ;

5.1.4拓展与提高

 ;

5.2文本类控件

 ;

5.2.1任务描述: 用户登录界面设计

 ;

5.2.2任务实现

 ;

5.2.3知识链接

 ;

5.2.4拓展与提高

 ;

5.3选择类控件

 ;

5.3.1任务描述: 学生信息添加界面设计

 ;

5.3.2任务实现

 ;

5.3.3知识链接

 ;

5.3.4拓展与提高

 ;

5.4Windows窗体事件处理机制

 ;

5.4.1任务描述: 简易计算器

 ;

5.4.2任务实现

 ;

5.4.3知识链接

 ;

5.4.4拓展与提高

 ;

5.5知识点提炼

 ;

第6章Windows应用程序开发进阶

 ;

6.1菜单、工具栏和状态栏

 ;

6.1.1任务描述: 学生成绩管理系统主窗体的完善

 

6.1.2任务实现

 

6.1.3知识链接

 

6.1.4拓展与提高

 

6.2数据显示控件

 

6.2.1任务描述: 设计学生信息查询界面

 

 

6.2.2任务实现

 

6.2.3知识链接

 

6.2.4拓展与提高

 

6.3通用对话框

 

6.3.1任务描述: 设计数据备份界面

 

6.3.2任务实现

 

6.3.3知识链接

 

6.3.4拓展与提高

 

6.4多文档界面应用程序

 

6.4.1任务描述: 多文档记事本程序

 

6.4.2任务实现

 

6.4.3知识链接

 

6.4.4拓展与提高

 

6.5知识点提炼

 

第7章ADO.NET数据访问技术

 

7.1连接数据库

 

7.1.1任务描述: 用户登录

 

7.1.2任务实现

 

7.1.3知识链接

 

7.1.4拓展与提高

 

7.2与数据库进行交互

 

7.2.1任务描述: 添加学生信息

 

7.2.2任务实现

 

7.2.3知识链接

 

7.2.4拓展与提高

 

7.3内存数据库

 

7.3.1任务描述: 学生信息查询

 

7.3.2任务实现

 

7.3.3知识链接

 

7.3.4拓展与提高

 

7.4数据浏览器——DataGridView控件

 

7.4.1任务描述: 学生信息查询

 

7.4.2任务实现

 

7.4.3知识链接

 

7.4.4拓展与提高

 

7.5知识点提炼

 

第8章Windows应用程序打包部署

 

8.1三层架构应用程序的开发

 

8.1.1任务描述: 三层架构的用户登录模块

 

8.1.2任务实现

 

8.1.3知识链接

 

8.1.4拓展与提高

 

8.2Windows应用程序的部署

 

8.2.1任务描述: 学生成绩管理系统的部署

 

8.2.2任务实现

 

8.2.3知识链接

 

8.2.4拓展与提高

 

8.3知识点提炼

 

第9章文件与数据流技术

 

9.1System.IO命名空间

 

9.1.1任务描述: 数据备份的实现

 

9.1.2任务实现

 

9.1.3知识链接

 

9.1.4拓展与提高

 

9.2文件和目录管理

 

9.2.1任务描述: 文件信息浏览

 

9.2.2任务实现

 

9.2.3知识链接

 

9.2.4拓展与提高

 

9.3数据流

 

9.3.1任务描述: 文件分割器

 

9.3.2任务实现

 

9.3.3知识链接

 

9.3.4拓展与提高

 

9.4知识点提炼

 

第10章图形图像处理技术

 

10.1GDI 绘图基础

 

10.1.1任务描述: 实现图形验证码

 

10.1.2任务实现

 

10.1.3知识链接

 

10.1.4拓展与提高

 

10.2常用图形绘制

 

10.2.1任务描述: 绘制学生成绩统计图

 

10.2.2任务实现

 

10.2.3知识链接

 

10.2.4拓展与提高

 

10.3图像处理

 

10.3.1任务描述: 简单图片浏览器

 

10.3.2任务实现

 

10.3.3知识链接

 

10.3.4拓展与提高

 

10.4知识点提炼

 

第11章多线程和网络编程

 

11.1多线程编程技术

 

11.1.1任务描述: 多线程自动更新界面

 

11.1.2任务实现

 

11.1.3知识链接

 

11.1.4拓展与提高

 

11.2网络编程基础

 

11.2.1任务描述: 设计点对点聊天程序

 

11.2.2任务实现

 

11.2.3知识链接

 

11.2.4拓展与提高

 

11.3知识点提炼

 

第12章WPF编程——让你的代码炫起来

 

12.1WPF应用程序开发入门

 

12.1.1任务描述: 用户登录

 

12.1.2任务实现

 

12.1.3知识链接

 

12.1.4拓展与提高

 

12.2使用WPF控件编程

 

12.2.1任务描述: 计算器程序

 

12.2.2任务实现

 

12.2.3知识链接

 

12.2.4拓展与提高

 

12.3数据绑定

 

12.3.1任务描述

 

12.3.2任务实现

 

12.3.3知识链接

 

12.3.4拓展与提高

 

12.4知识点提炼

 

第13章综合案例——学生成绩管理系统

 

13.1学生成绩管理系统的分析与设计

 

13.1.1系统概述

 

13.1.2系统业务流程

 

13.1.3数据库设计

 

13.2学生成绩管理系统的实现

 

13.2.1表示层的实现

 

13.2.2业务逻辑层的实现

 

13.2.3数据访问层的实现

 

13.3学生成绩管理系统的部署

 

参考文献

媒体评论

评论

前沿

前言

C#(发音为C Sharp)语言是微软公司专为.NET平台量身定做的编程语言,是一种简洁、类型安全的面向对象的编程语言,开发人员通过它可以编写在.NET Framework上运行的各种安全可靠的应用程序。自2002年推出以来,C#语言以其易学易用、功能强大的优势被广泛应用。目前,C#语言已经成为ECMA与ISO标准规范,是当前最主流的开发语言之一。因此,学习和掌握C#程序开发技术,对于在校学生和求职应聘者来说都具有极其重要的意义。为了帮助读者掌握C#程序开发技术,提高软件开发能力,结合学习.NET技术以及多年程序开发和教学的经验,编者编写了本书。全书以项目为载体,以工作过程为导向,将学生成绩管理系统项目分解成不同的知识单元,分散到不同的章节,强调理论和实践的有机融合,注重编码规范,突出软件开发能力的训练与培养,使读者养成良好的软件开发规范,更快步入软件开发的大门。本书具有以下特点: (1) 紧贴市场需求,内容实用新颖。全书以企业对.NET开发人员要求的知识和技能来精心选择内容,由浅入深地介绍了.NET开发人员必备的C#程序设计基本知识和技能,突出重点,强调实用。(2) 按照“教学做”一体化设计教学单元。全书按照“提出问题(任务描述)—解决问题(任务实现)—问题探究(知识链接)—拓展与提高”来安排每一节内容,符合学习者的认知规律,能够有效提高读者的学习兴趣,培养读者自主学习和探究能力。(3) 以实际项目为载体,注重案例的实用性。全书以学生成绩管理系统开发为载体,以系统功能模块的设计和开发为案例,强调案例的实用性,将实例融入到知识讲解中,使知识和实例相辅相成,既有利于读者学习知识,又能为读者进行实际项目开发提供实践指导。(4) 配套资源丰富。本书提供教学课件、教学设计以及所有实例的源代码以方便读者使用。有需要的读者可以到清华大学出版社网站下载或者与作者联系。本书以C# 4.5及Visual Studio 2013为例全面介绍了利用C#语言开发应用程序的相关技术。全书共13章,第1~3章以开发基于控制台的学生成绩管理系统为主线,深入讨论了C#程序的结构、数据类型和表达式、程序流程控制以及数组、字符串和集合等内容; 第4章围绕改进的控制台学生成绩管理系统的开发,介绍了C#面向对象程序设计的核心技术和知识; 第5~10章围绕基于WinForm的学生成绩管理系统的开发,全面介绍了Windows应用程序开发、数据库应用开发、文件与数据流技术、图形图像处理等核心技术; 第11~12章介绍了多线程和网络编程以及WPF程序开发技术; 第13章给出了基于三层架构的学生成绩管理系统的完整设计与实现以及部署。本书由许昌学院曾宪权、曹玉松编写,具体分工如下: 第1~3章由曹玉松编写,第4~13章由曾宪权编写。全书由曾宪权统稿、修改和定稿。本书在编写过程中,参考了大量的相关书籍和网络资源,在此对相关作者表示感谢。在编写过程中,尽管我们已经很努力,但由于水平的限制,疏漏之处在所难免,恳请广大读者批评指正。如有什么意见和建议,请联系我们,邮箱是xianquanzeng@126.com。编者2016年8月

免费在线读

第3章数组、字符串和集合

C#程序设计中,数组和字符串是最常用的数据类型。数组能够按照一定的规律把相关的数据组织起来,利用字符串可以处理大量与文本相关的问题,集合可以存储多个数据。本章将对数组、字符串和集合的相关知识进行详细介绍。通过本章的学习,读者可以:  了解数组的基本概念。 掌握一维数组和二维数组的使用。 了解字符串的概念,熟悉字符串的声明和使用。 掌握常用字符串的操作方法。 掌握可变字符串类StringBuilder的定义和用法。 掌握常用集合类的功能和用法。3.1数组3.1.1任务描述: 学生信息输入和输出
学生成绩管理系统需要输入学生的信息并保存,然后按照一定的格式进行输出。本情景完成学生成绩管理系统V0.8学生信息的输入和输出,如图31所示。

图31学生信息输入和输出

3.1.2任务实现(1) 启动Visual Studio 2013,新建控制台项目Project0301。(2) 项目初始化以后,在主窗口显示的文件的Main()方法中添加如下代码行: 
static void Main(string[] args)
{
const int NUM = 3;//学生人数
string[,] student = new string[NUM, 7];//二维数组声明
InputStudent(student,NUM); //调用学生信息输入方法
OutputStudent(student,NUM);//调用学生信息输出方法
}
//学生信息输入方法
static void InputStudent(string[,] student, int num)
{
for (int i = 0; i < num; i ) //重复输入学生信息
{
Console.Write("请输入第{0}个学生的学号: ", i 1);
student[i, 0] = Console.ReadLine();
Console.Write("请输入第{0}个学生的姓名: ", i 1);
student[i, 1] = Console.ReadLine();
Console.Write("请输入第{0}个学生的语文成绩: ", i 1);
student[i, 2] = Console.ReadLine();
Console.Write("请输入第{0}个学生的数学成绩: ", i 1);
student[i, 3] = Console.ReadLine();
Console.Write("请输入第{0}个学生的英语成绩: ", i 1);
student[i, 4] = Console.ReadLine();
//计算总分
int temp = Convert.ToInt32(student[i, 2]) Convert.ToInt32(student[i, 3]) Convert.ToInt32(student[i, 4]);
student[i, 5] = Convert.ToString(temp);
student[i, 6] = string.Format("{0:F2}", temp / 3.0);
}
}
//学生信息输出
static void OutputStudent(string[,] student, int num)
{
//输出学生成绩
Console.WriteLine("学生成绩单");
Console.WriteLine("|----------------------------------|");
Console.WriteLine("| 学号 | 姓 名 |语文|数学|英语|总 分|平均分|");
Console.WriteLine("|----------------------------------|");
for (int i = 0; i < num; i )
{
Console.WriteLine("|{0,8}|{1,3}|{2,4}|{3,4}|{4,4}|{5,5}|{6,6:f2}|", student[i, 0], student[i, 1], 
student[i, 2], student[i, 3], student[i, 4], student[i, 5], student[i, 6]);
 Console.WriteLine("|----------------------------------|");
}
}3.1.3知识链接数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素。通常情况下,数组的元素类型必须相同。数组中的每个元素都有一个编号,这个编号称为下标,可以通过下标来区别数组元素。数组的下标从0开始。数组元素的个数称为数组的长度。数组可以分为一维数组、多维数组和交错数组等。3.1.3.1一维数组一维数组是只含有一个下标的数组,在C#语言中,采用下列方式来声明一个一维数组: 

[]

其中,

是数组存储元素的数据类型,可以是任何类型。

是数组的名称。数组必须在访问之前初始化。数组的初始化有两种方式。可以给定数组元素值的形式来指定数组的完整内容,也可以指定数组的大小,再使用关键字new初始化所有数组元素。使用给定元素值的指定数组,只需要提供一个用逗号分隔的元素值列表,该列表必须放在花括号{}中,例如: 

int[]myIntArray = {5,9, 10, 2, 99};其中,数组myIntArray有5个元素,每个元素被赋予了一个整数值。另一种数组初始化方式的语法如下: 

int[]myIntArray = new int[5];这里使用关键字new显示初始化数组,用一个常量值定义其大小。这种方法会给所有数组元素赋予同一个默认值,对于数值类型来说,其默认值是0。还可以将这两种初始化方式组合在一起使用。例如: 

int[] myIntArray = new int[5] {5,9, 10, 2, 99};使用这种方式,数组大小必须与元素个数相匹配。例如,不能编写如下代码: 

int []myInyArray = new int[10] {5,9,10,2,99};其中,数组有10个元素,但只定义了5个元素,所以会编译失败。也可以使用常量来定义数组的大小。例如: 

constintarraySize=5;

int [] myIntArray =new int[arraySize] {5,9, 10, 2, 99};与其他变量一样,并非必须在声明数组的代码行中初始化数组,下列代码也是合法的: 

int []myInyArray;

myIntArray = new int[5];【例3.1】使用随机数生成一个含有10个元素的整数数组,接收插入数据的位置和数据,将数据插入到指定位置,然后输出数组。新建控制台程序Chapter0301,在Program.cs文件中添加如下代码: 

static void Main(string[] args)

{

int[] myIntArray = new int[11];//声明数组

Randomram=new Random ();//随机数对象

for (int i = 0; i < 10; i ) //利用循环完成数组初始化

{

 myIntArray[i] = ram.Next(100, 999); //随机生成(100,99)之间的整数

}

Console.WriteLine("插入前的数组: ");

foreach (int m in myIntArray )//遍历数组

{

Console.Write("{0,4}",m);//输出数组元素的值

}

Console.Write("\n 输入插入位置(0-9): ");

int pos = Convert.ToInt32(Console.ReadLine());

Console.Write(" 输入插入数据: ");

int number = Convert.ToInt32(Console.ReadLine());

for(int k=myIntArray.Length-1;k>pos;k--)//数组元素移位

{

myIntArray[k] = myIntArray[k - 1];

}

myIntArray[pos] = number;

Console.WriteLine("插入后的数组: ");

foreach (int m in myIntArray)//遍历数组

{

Console.Write("{0,4}", m);//输出数组元素的值

}

Console.ReadKey();

}程序的运行结果如图32所示。

图32程序Chapter0301的运行结果

【说明】.NET Framework中提供了一个专门产生随机数的类System.Random。在C#中利用Random类产生随机数的步骤如下: (1) 创建Random对象: Random ran=new Random();(2) 使用Random类的Next方法生成指定范围的随机数。具体用法如下:  Random.Next(): 返回非负随机数。 Random.Next(Int): 返回一个小于所指定最大值的非负随机数。 Random.Next(Int,Int): 返回一个指定范围内的随机数,例如(-100,0)返回负数。3.1.3.2多维数组多维数组是使用多个下标访问其元素的数组。例如,要确定一座山相对于某位置的高度,可以使用两个坐标x和y来确定位置。把这两个坐标用作下标,就可以定义二维数组来存储大山的高度。在C#中,可以采用下列方式来声明一个二维数组: 


[,]

; 类似的,声明多维数组只需要使用多个逗号(,)。例如: 


[,,,]

; 该语句声明了一个4维数组。多维数组的初始化和一维数组类似,可以使用关键字new来动态初始化数组或者通过给定值的形式来指定数组中的全部内容。例如: 

double[,] hillHeight = new double[3,4]{1,2,3,4},{2,3,4,5},{3,4,5,6}};

double[,] hillHeight = {1,2,3,4},{2,3,4,5},{3,4,5,6}};图33给出了上面声明的数组hillHeight的存储结构。

图33二维数组的存储结构

要访问多维数组中的元素,只需要指定它们的下标,并用逗号(,)分开,例如,表达式hillHeight[2,1]将访问上面定义的数组hillHeight的第3行中的第2个元素(它的值是4)。3.1.3.3交错数组前面介绍的多维数组每一行的元素都相同,因此可称为矩形数组。如果多维数组中每一行的元素个数不同,这样就构成了交错数组。交错数组被称为数组中的数组,因为它的每个元素都是另一数组。图34比较了有3×3个元素的二维数组和交错数组。图中的交错数组有3行,第一行有2个元素,第二行有6个元素,第三行有3个元素。

图34交错数组示例

在声明交错数组时,要依次放置开闭括号。在初始化交错数组时,先设置该数组包含的行数。定义各行中元素个数的第二个括号设置为空,因为这类数组的每一行包含不同的元素数。然后,为每一行指定行中的元素个数。例如: 

int[][] jagged = new int[3][];

jagged[0] = new int[2] {1, 2};

jagged[1] = new int[6] {3, 4, 5, 6, 7, 8};

jagged[2] = new int[3] {9, 10, 11};迭代交错数组中所有元素的代码可以放在嵌套的for循环中。在外层的for循环中,迭代每一行,内层的for循环迭代一行中的每个元素。例如: 

for ( int row = 0; row < jagged.Length; row )

{

for ( int element = 0; element

{

Console.WriteLine("row: {0}, element: [1], value: {2}",row, element,


}

}在交错数组中,数组中的数组都必须具有相同的数据类型。3.1.4拓展与提高复习本节内容,掌握C#数组的定义与使用,思考并完成以下任务: (1) 数组常用的操作有查找、插入和排序。定义一个数组,在该数组上实现查询、插入和排序操作,掌握数组的用法。(2) 输入一个m*n和n*p的矩阵,编程计算两个矩阵的乘积。(3) 输入一个m行和n列的矩阵,编写程序计算每一行和每一列的和,并存储在该矩阵的最后一行和最右边一列。(4) 输入若干个学生的学号、姓名和三门课程的成绩,计算学生的总分,并按照总分由高到低的顺序输出学生信息表。3.2字符串处理3.2.1任务描述: 学生信息输入和输出

学生成绩管理系统需要输入学生的信息并保存,然后按照一定的格式进行输出。本情景进一步完善学生信息的输入和输出,将学生信息作为一个整体进行输入和处理,如图35所示。

图35学生信息输入和输出

3.2.2任务实现(1) 启动Visual Studio 2013,新建控制台项目Project0302。(2) 项目初始化以后,在主窗口显示的文件的Main()方法中添加如下代码行: 

static void Main(string[] args)

{

const int NUM = 3;//学生人数

string[,] student = new string[NUM, 7];//二维数组声明

InputStudent(student, NUM); //调用学生信息输入方法

OutputStudent(student, NUM);//调用学生信息输出方法

}

//学生信息输入方法

static void InputStudent(string[,] student, int num)

{

int temp;

string strStudent = string.Empty;

string[] strInfo;

for (int i = 0; i < num; i ) //输入学生信息

{

Console.Write("输入第{0}个学生信息(以顿号分割): ", i 1);

strStudent = Console.ReadLine();

strInfo = strStudent.Split(、); //分隔字符串

for (int j = 0; j < strInfo.Length; j )

 {

student[i, j] = strInfo[j];

}

//计算总分

temp = Convert.ToInt32(student[i, 2]) Convert.ToInt32(student[i, 3]) Convert.ToInt32(student[i, 4]);

student[i, 5] = Convert.ToString(temp);

student[i, 6] = string.Format("{0:F2}", temp/3.0);

}

}

//学生信息输出

static void OutputStudent(string[,] student, int num)

{

//输出学生成绩

Console.WriteLine("学生成绩单");

Console.WriteLine("|----------------------------------|");

Console.WriteLine("| 学号 | 姓 名 |语文|数学|英语|总 分|平均分|");

Console.WriteLine("|----------------------------------|");

for (int i = 0; i < num; i )

{

Console.WriteLine("|{0,8}|{1,3}|{2,4}|{3,4}|{4,4}|{5,5}|{6,6:f2}|", student[i, 0], student[i, 1],

student[i, 2], student[i, 3], student[i, 4], student[i, 5], student[i, 6]);

Console.WriteLine("|-------------------------------------------|");

}

}3.2.3知识链接3.2.3.1字符串概述

字符串是C#最重要的数据类型之一,是.NET Framework中String类的对象。String对象是System.Char对象的有序集合,它的值是该有序集合的内容,而且该值是不能改变的。System.Char类只定义了一个Unicode字符。Unicode字符是目前计算机中通用的字符编码,它为不同语言中的每个字符设定了统一的二进制编码,用于满足跨平台、跨语言的文本转换和处理要求。由于字符串是由零个或多个字符组成,可以根据字符在字符串的索引值来获取字符串中的某个字符。字符在字符串中的索引从0开始。例如,字符串Hello C#!中第一个字符是H,它在字符串中的索引值为0。字符串中可以包含转义字符对其中的内容进行转义,也可以在前面加@符号使其中的所有内容不再进行转义。例如: 

string path="C:\\xcu\\xcu.java";//使用转义字符

string path=@"C:\xcu\xcu.java";  //前面加上@在C#中,string关键字是String的别名。因此,String与string等效,可以根据自己的喜好选择命名约定。可以通过各种方式来声明和初始化字符串,例如: 

string message1; //没有初始化

string message2 = null;//将字符串初始化为null

string message3 = System.String.Empty; //将字符串初始化为空字符""

string oldPath = "c:\\Program Files\\Microsoft Visual Studio 13.0";//用转义字符初始化字符串

string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0"; //用@来实现转义字符

System.String greeting = "Hello World!";//使用系统String类

//使用字符数组初始化字符串

char[] letters = { A, B, C };

string alphabet = new string(letters);注意: 除了在使用字符数组初始化字符串时以外,不要使用new关键字创建字符串对象。使用Empty常量值初始化字符串可新建字符串长度为零的String对象。零长度字符串的字符串表示形式为""。使用Empty值(而不是null)初始化字符串可以降低发生NullReferenceException的可能性。请在尝试访问字符串之前使用静态IsNullOrEmpty(String)方法验证字符串的值。C#字符串末尾没有以null结尾的字符,因此C#字符串可以包含任意数目的嵌入式null字符(\0)。字符串的Length属性代表它包含的Char对象的数量,而不是Unicode字符的数量。C#中提供了比较全面的字符串处理方法,字符串类String封装了大量的字符串操作方法,利用这些方法,开发者可以完成完成绝大部分的字符串操作功能。3.2.3.2字符串操作1. 字符串比较

比较字符串时,产生的结果会是一个字符串大于或小于另一个字符串,或者两个字符串相等。根据执行的是序号比较还是区分区域性比较,确定结果时所依据的规则会有所不同。对特定的任务使用正确类型的比较十分重要。在String类中,常见的比较字符串的方法有Compare()、CompareTo()、CompareOrdinal()以及Equals()等。1) Compare()方法Compare()方法是String类的静态方法,用于全面比较两个字符串对象。它有多个重载形式,其中最常用的两种方法如下: 

Int Compare(string strA, string strB)

Int Compare(string strA, string strB, bool ignoreCase)其中,strA、strB为待比较的两个字符串,ignoreCase指定是否考虑大小写,当其值取true时忽略大小写。表31给出了Compare()方法可能的返回值。

表31Compare()方法可能的返回值

返回值条件

负整数在排序顺序中,第一个字符串在第二个字符串之前,或者第一个字符串是null0第一个字符串和第二个字符串相等,或者两个字符串都是null正整数或者1在排序顺序中,第一个字符串在第二个字符串之后或者第二个字符串是null下列示例使用Compare()方法来确定两个字符串的相对值。

string MyString = "Hello World!";

Console.WriteLine(String.Compare(MyString, "Hello World?"));//此示例向控制台显示 -12) CompareTo()方法CompareTo()方法比较当前字符串对象封装到另一个字符串或对象的字符串。此方法的返回值与表31中Compare()方法返回的值相等。下列示例使用CompareTo()方法来比较MyString对象和OtherString对象。

string MyString = "Hello World";

string OtherString = "Hello World!";

int MyInt = MyString.CompareTo(OtherString);

Console.WriteLine( MyInt );//向控制台显示 13) CompareOrdinal()方法CompareOrdinal()方法比较两个字符串对象而不考虑本地区域性。此方法的返回值与表31中Compare()方法返回的值相等。下列示例使用CompareOrdinal()方法来比较两个字符串的值。

string MyString = "Hello World!";

Console.WriteLine(String.CompareOrdinal(MyString, "hello world!"));//向控制台显示-324) Equals()方法Equals方法能够轻松确定两个字符串是否相等。这个区分大小写的方法返回true或false布尔值。它可以在现有类中使用,如下面的示例所示。下面的示例使用Equals()方法来确定一个字符串对象是否包含短语Hello World。

string MyString = "Hello World";

Console.WriteLine(MyString.Equals("Hello World"));//此示例向控制台显示true此方法还可作为静态方法使用。下列示例使用静态方法比较两个字符串对象: 

string MyString = "Hello World";

string YourString = "Hello World";

Console.WriteLine(String.Equals(MyString, YourString));//向控制台显示true2. 字符串的搜索1) IndexOf方法可以使用IndexOf方法来确定特定字符在字符串中的第一个匹配项的位置。这个区分大小写的方法使用从零开始的索引从字符串的开头开始计数,并返回所传递字符的位置。如果无法找到该字符,则返回值-1。以下示例使用IndexOf()方法搜索字符l在字符串中的第一个匹配项。

string MyString = "Hello World";

Console.WriteLine(MyString.IndexOf(l));//向控制台显示22) LastIndexOf方法LastIndexOf方法类似于IndexOf()方法,但它返回特定字符在字符串中的最后一个匹配项的位置。它不区分大小写,并且使用从零开始的索引。以下示例使用LastIndexOf()方法搜索字符l在字符串中的最后一个匹配项。

string MyString = "Hello World";

Console.WriteLine(MyString.LastIndexOf(l));//向控制台输出93. 格式化字符串格式字符串是内容可以在运行时动态确定的一种字符串。使用String类的静态方法Format并在大括号中嵌入占位符来格式化字符串,这些占位符将在运行时替换为其他值。Format方法的基本语法如下: 

public static string Format(string format,object obj);其中,Format用来指定字符串要格式化的形式,由零个或多个固定文本段与一个或多个格式项混和组成,其中索引占位符称为格式项,对应于列表中的对象。obj代表要格式化的对象列表。下列示例说明了格式字符串的用法: 

//数值化输出

Console.WriteLine(string.Format("{0:C2}",2)); //C2表示货币,其中2表示小数点后位数

Console.WriteLine(string.Format("{0:D2}",2)); //D2表示十进制位数,其中2表示位数,

//不足用0占位

Console.WriteLine(string.Format("{0:E3}",22233333220000));

//E3表示科学计数法,其中3表示小数点后保留位数

Console.WriteLine(string.Format("{0:N}",2340000));//N表示用分号隔开的数字

Console.WriteLine(string.Format("{0:X}",12345)); //X表示十六进制

Console.WriteLine(string.Format("{0:G}",12)); //常规输出

//按提供的格式(000.00->012.00,0.0->12.0)格式化的形式输出

Console.WriteLine(string.Format("{0:000.00}",12));

Console.WriteLine(string.Format("{0:F3}",12));//F浮点型,其中3表示小数点位数4. 截取字符串截取字符串需要使用string类的Substring()方法,该方法从原始字符串中指定位置截取和指定长度的字符,返回一个新的字符串。该方法的基本语法如下: 

Substring(int startindex, int length) 其中,参数startindex索引从0开始,且最大值必须小于源字符串的长度,否则会编译异常; 参数length的值必须不大于源字符串索引指定位置开始之后的字符串字符总长度,否则会出现异常。例如: 

string s4="VisualC#Express";

System.Console.WriteLine(s4.Substring(7,2)) ;//outputs"C#"下列示例演示了如何从文件全名中获取文件的路径和文件名。

string strAllPath="D:\\DataFiles\\Test.mdb"; //定义一个字符串,存储文件全名

string strPath=strAllPath.Substring(0, strAllPath.LastIndexOf("\\") 1);//获取文件路径

string strPath=strAllPath.Substring(strAllPath.LastIndexOf("\\") 1); //获取文件名5. 拆分字符串String类的Split()方法用于拆分字符串,此方法的返回值是包含所有拆分子字符串的数组对象,可以通过数组取得所有分隔的子字符串。其基本语法如下: 

public string[] Split(params char[] separator)

例3.2演示如何使用Split()方法分析字符串。作为输入,Split()方法采用一个字符数组指示哪些字符被用作分隔符。本示例中使用了空格、逗号、句点、冒号和制表符。一个含有这些分隔符的数组被传递给Split,并使用结果字符串数组分别显示句子中的每个单词。【例3.2】新建控制台程序Chapter0302,在Program.cs文件中输入如下代码: 

static void Main()

{

char[] delimiterChars = { , ,, ., :, \t };

string text = "one\ttwo three:four,five six seven";

System.Console.WriteLine("Original text: {0}", text);

string[] words = text.Split(delimiterChars);

System.Console.WriteLine("{0} words in text:", words.Length);

foreach (string s in words)

{

 System.Console.WriteLine(s);

}

}程序的运行结果如图36所示。

图36程序Chapter0302的运行结果

6. 串联多个字符串串联是将一个字符串追加到另一个字符串末尾的过程。若要串联字符串变量,可以使用 或 =运算符,也可以使用字符串的Concat()、Join()方法。 运算符容易使用,且有利于提高代码的直观性。注意: 在字符串串联操作中,C#编译器对null字符串和空字符串进行相同的处理,但它不转换原始null字符串的值。1) Concat()方法Concat()方法用于连接两个或多个字符串。Concat()方法也有多个重载形式,最常用的格式如下: 

public static string Concat(paramsstring[] values);其中,参数values用于指定所要连接的多个字符串。例如: 

newStr=String.Concat(strA," ",strB);

Console.WriteLine(newStr);//"Hello World"2) Join()方法Join()方法利用一个字符数组和一个分隔符串构造新的字符串,常用于把多个字符串连接在一起,并用一个特殊的符号来分隔开。Join方法的常用形式如下: 

public static string Join(stringseparator,string[] values);其中,参数values为指定的分隔符,而values用于指定所要连接的多个字符串数组。下例用^^分隔符把Hello和World连起来。

newStr="";

String[] strArr={strA,strB};

newStr=String.Join("^^",strArr);

Console.WriteLine(newStr);//"Hello^^World"3) 连接运算符 String类支持连接运算符 ,可以方便地连接多个字符串。例如,下例把Hello和World连接起来。

newStr="";

newStr=strA strB;

Console.WriteLine(newStr);//"HelloWorld"7. 插入和填充字符串String类包含了在一个字符串中插入新元素的方法,可以用Insert()方法在任意插入任意字符。Insert方法用于在一个字符串的指定位置插入另一个字符串,从而构造一个新的串。Inse()rt方法也有多个重载形式,最常用的格式如下: 

public string Insert(int startIndex,string value);其中,参数startIndex用于指定所要插入的位置,从0开始索引; value指定所要插入的字符串。下列示例在Hello的字符H后面插入World,构造一个串HWorldello。

newStr="";

newStr=strA.Insert(1,strB);

Console.WriteLine(newStr); //"HWorldello"8. 删除和剪切字符串1) Remove()方法Remove方法从一个字符串的指定位置开始,删除指定数量的字符。最常用的形式为: 

public string Remove(int startIndex,int count);其中,参数startIndex用于指定开始删除的位置,从0开始索引; count指定删除的字符数量。下例中把Hello中的ell删掉。

newStr=strA.Remove(1,3);Console.WriteLine(newStr);//"Ho"2) Trim()方法若想把一个字符串首尾处的一些特殊字符剪切掉,例如去掉一个字符串首尾的空格等,可以使用String的Trim()方法。其格式如下: 

public string Trim();

public string Trim(paramschar[] trimChars);其中,参数trimChars数组包含了指定要去掉的字符,如果默认,则删除空格符号。下面的示例中实现了对@Hello#$的净化,去掉首尾的特殊符号。

newStr="";

char[] trimChars={@,#,$, };

String strC="@Hello# $";

newStr=strC.Trim(trimChars);

Console.WriteLine(newStr);//"Hello"9. 复制字符串String类包括了复制字符串方法Copy()和CopyTo(),可以完成对一个字符串及其一部分的复制操作。1) Copy()方法若想把一个字符串复制到另一个字符数组中,可以使用String的静态方法Copy()方法来实现,其形式为: 

public string Copy(string str);其中,参数str为需要复制的源字符串,方法返回目标字符串。

2) CopyTo()方法CopyTo()方法可以实现与Copy()同样的功能,但功能更为丰富,可以复制字符串的一部分到一个字符数组中。另外,CopyTo()方法不是静态方法,其形式为: 

public void CopyTo(int sourceIndex,char[] destination,int destinationIndex,int count);其中,参数sourceIndex为需要复制的字符起始位置,destination为目标字符数组,destinationIndex指定目标数组中的开始存放位置,而count指定要复制的字符个数。下面的示例中,把strA字符串Hello中的ell复制到newCharArr中,并在newCharArr中从第2个元素开始存放。

char[] newCharArr=new char[100];

strA.CopyTo(2,newCharArr,0,3);

Console.WriteLine(newCharArr);//"Hel"10. 替换字符串要替换一个字符串中的某些特定字符或者某个子串,可以使用Replace()方法来实现,其形式为: 

public string Replace(char oldChar, char newChar);

public string Replace(string oldValue, string newValue);其中,参数oldChar和oldValue为待替换的字符和子串,而newChar和newValue为替换后的新字符和新子串。下面的示例把Hello通过替换变为Hero。

newStr=strA.Replace("ll","r");

Console.WriteLine(newStr);由于字符串是不可变的,因此一个字符串对象一旦创建,值就不能再更改(在不使用不安全代码的情况下)。在使用其他方法(如插入、删除操作)时,都要在内在中创建一个新的String对象,而不是在原对象的基础上进行修改,这就需要开辟新的内存空间。如果需要经常进行串修改操作,使用String类无疑是非常耗费资源的,这时需要使用StringBuilder类。3.2.3.3可变字符串与String类相比,StringBuilder类可以实现动态字符串。此外,动态的含义是指在修改字符串时,系统不需要创建新的对象,不会重复开辟新的内存空间,而是直接在原StringBuilder对象的基础上进行修改。1. 创建可变字符串StringBuilder类位于命名空间System.Text中,使用时,可以在文件头通过using语句引入该空间。创建一个可变字符串StringBuilder对象需要使用new关键字,并可以对其进行初始化。下面的语句声明了一个StringBuilder对象myStringBuilder,并初始化为Hello: 

StringBuilder myStringBuilder=new StringBuilder("Hello");如果不使用using语句在文件头引入System.Text命名空间,也可以通过空间限定来声明StringBuilder对象: 

System.Text.StringBuildermyStringBuilder=new StringBuilder("Hello");在声明时,也可以不给出初始值,然后通过其他方法进行赋值。2. 设置可变字符串容量StringBuilder对象为动态字符串,可以对其设置好的字符数量进行扩展。另外,还可以设置一个最大长度,这个最大长度称为该StringBuilder对象的容量(Capacity)。为StringBuilder设置容量的意义在于,当修改StringBuilder字符串时,当其实际字符长度(即字符串已有的字符数量)未达到其容量之前,StringBuilder不会重新分配空间; 当达到容量时,StringBuilder会在原空间的基础之上,自动进行设置。StringBuilder默认初始分配16个字符长度。有两种方式来设置一个StringBuilder对象的容量。1) 使用构造函数StringBuilder构造函数可以接受容量参数。例如,下面声明一个StringBuilder对象sb2,并设置其容量为100。

//使用构造函数

StringBuilder sb2=new StringBuilder("Hello",100);2) 使用Capacity读/写属性Capacity属性指定StringBuilder对象的容量。例如,下面语句首先声明一个StringBuilder对象sb3,然后利用Capacity属性设置其容量为100。

//使用Capacity属性

StringBuilder sb3=new StringBuilder("Hello");

sb3.Capacity=100;3. 追加操作追加一个StringBuilder是指将新的字符串添加到当前StringBuilder字符串的结尾处,可以使用Append()和AppendFormat()方法来实现这个功能。1) Append()方法Append方法实现简单的追加功能,常用形式为: 

public StringBuilder Append(object value);其中,参数value既可以是字符串类型,也可以是其他的数据类型,如bool、byte、int等。例如,把一个StringBuilder字符串“Hello”追加为“Hello World!”。

//Append

StringBuilder sb4=new StringBuilder("Hello");

sb4.Append(" World!");2) AppendFormat()方法AppendFormat()方法可以实现对追加部分字符串的格式化,可以定义变量的格式,并将格式化后的字符串追加在StringBuilder后面。常用的形式为: 

StringBuilder AppendFormat(string format,params object[] args);其中,args数组指定所要追加的多个变量。format参数包含格式规范的字符串,其中包括一系列用大括号括起来的格式字符,如{0:u}。这里,0代表对应args参数数组中的第0个变量,而u定义其格式。下例中,把一个StringBuilder字符串Today is追加“Today is *当前日期*\”。

//AppendFormat

StringBuilder sb5=new StringBuilder("Today is ");

sb5.AppendFormat("{0:yyyy-MM-dd}",System.DateTime.Now);

Console.WriteLine(sb5); //形如: "Today is 2008-10-20"4. 插入操作StringBuilder的插入操作是指将新的字符串插入到当前的StringBuilder字符串的指定位置,如Hello变为Heeeello。可以使用StringBuilder类的Insert()方法来实现这个功能。常用形式为: 

public StringBuilder Insert(int index, object value);其中,参数index指定所要插入的位置,并从0开始索引,如index=1,则会在原字符串的第2个字符之前进行插入操作; 同Append一样,参数value并不仅是只可取字符串类型。通过上面的介绍,可以看出StringBuilder与String在许多操作上是非常相似的。在操作性能和内存效率方面,StringBuilder要比String好得多,可以避免产生太多的临时字符串对象,特别是对于经常重复进行修改的情况更是如此。而另一方面,String类提供了更多的方法,可以使开发能够更快地实现应用。在两者的选择上,如果应用对于系统性能、内存要求比较严格,以及经常处理大规模的字符串,推荐使用StringBuilder对象; 否则,可以选择使用String。3.2.4拓展与提高在编写字符串的处理程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。到目前为止,许多编程语言和工具都包含对正则表达式的支持,C#也不例外,C#基础类库中包含有一个命名空间(System.Text.RegularExpressions)和一系列可以充分发挥正则表达式威力的类(Regex、Match、Group等)。借助网络资源,了解C#正则表达式的用法,提高程序设计技能。3.3集合3.3.1任务描述: 学生信息存储

在学生成绩管理系统中,需要将学生信息保存起来以便进行相应的处理。本情景利用集合来存储学生的信息,并按照一定的格式将信息输出,如图37所示。

图37学生列表

3.3.2任务实现(1) 启动Visual Studio 2013,新建控制台项目Project0303。(2) 项目初始化以后,在主窗口显示的Program.cs文件中添加如下代码: 

public struct Student //学生结构体定义

{

publicstring id;

publicstring name;

publicstring grade1;

publicstring grade2;

publicstring grade3;

publicint total;

publicfloat average;

}

static void Main(string[] args)

{

const int NUM = 3;//学生人数

Student stu; //声明学生结构

List

listStudent = new List

();//建立学生列表

for (int i = 0; i < NUM; i ) //输入学生信息

{

Console.Write("输入第{0}个学生学号: ", i 1);

stu.id = Console.ReadLine();

Console.Write("输入第{0}个学生姓名: ", i 1);

stu.name = Console.ReadLine();

Console.Write("输入第{0}个学生语文成绩: ", i 1);

stu.grade1 = Console.ReadLine();

Console.Write("输入第{0}个学生数学成绩: ", i 1);

stu.grade2 = Console.ReadLine();

Console.Write("输入第{0}个学生英语成绩: ", i 1);

stu.grade3 = Console.ReadLine();

//计算总分和平均分

stu.total = Convert.ToInt32(stu.grade1) Convert.ToInt32(stu.grade2) Convert.ToInt32(stu.grade3);

stu.average = (float)(stu.total / 3.0);

listStudent.Add(stu);//添加学生到学生列表

}

//输出学生成绩

Console.WriteLine("学生成绩单");

Console.WriteLine("|-------------------------------------------|");

Console.WriteLine("| 学号 | 姓名 |语文|数学|英语|总 分|平均分|");

Console.WriteLine("|-------------------------------------------|");

foreach (var s in listStudent) //遍历学生列表

{

Console.WriteLine("|{0,8}|{1,3}|{2,4}|{3,4}|{4,4}|{5,5}|{6,6:f2}|", s.id, s.name, s.grade1, s.grade2,s.grade3, s.total, s.average);

Console.WriteLine("|-------------------------------------------|");

}

}3.3.3知识链接3.3.3.1集合类

对于很多应用程序,需要创建和管理相关对象组。有两种方式可以将对象分组: 创建对象数组以及创建对象集合。数组对于创建和处理固定数量的强类型对象最有用。集合提供一种更灵活的处理对象组的方法。与数组不同,处理的对象组可根据程序更改的需要动态地增长和收缩。集合是类,因此必须声明新集合后,才能向该集合中添加元素。许多常见的集合是由.NET Framework提供的。每一类型的集合都是为特定用途设计的。可以通过使用System.Collections.Generic命名空间中的类来创建泛型集合。在.NET 2.0之前,不存在泛型。现在泛型集合类通常是集合的首选类型。泛型集合类是类型安全的,如果使用值类型,是不需要装箱操作的。如果要在集合中添加不同类型的对象,且这些对象不是相互派生的,例如在集合中添加int和string对象,就只需基于对象的集合类。表32列出了System.Collections.Generic命名空间中一些常用集合类的功能。

表32System.Collections.Generic命名空间中一些常用集合类的功能

类描述

Dictionary

表示根据键进行组织的键/值对的集合List

表示可通过索引访问的对象的列表。提供用于对列表进行搜索、排序和修改的方法Queue

表示对象的先进先出(FIFO)集合SortedList

表示根据键进行排序的键/值对的集合,而键基于的是相关的IComparer

实现Stack

表示对象的后进先出(LIFO)集合在.NET Framework 4中,System.Collections.Concurrent命名空间中的集合可提供有效的线程安全操作,以便从多个线程访问集合项。当有多个线程并发访问集合时,应使用System.Collections.Concurrent命名空间中的类代替System.Collections.Generic和System.Collections命名空间中的对应类型。System.Collections命名空间中的类不会将元素存储为指定类型的对象,而是存储为Object类型的对象。只要有可能,就应使用System.Collections.Generic或System.Collections.Concurrent命名空间中的泛型集合来替代System.Collections命名空间中的旧类型。表33列出了一些System.Collections命名空间中常用的集合类。

表33System.Collections命名空间中常用的集合类

类描述

ArrayList表示大小根据需要动态增加的对象数组Hashtable表示根据键的哈希代码进行组织的键/值对的集合Queue表示对象的先进先出(FIFO)集合Stack表示对象的后进先出(LIFO)集合3.3.3.2列表.NET Framework为动态列表提供了类ArrayList和List。ArrayList代表了可被单独索引的对象的有序集合。它基本上可以替代一个数组。但是,与数组不同的是,可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。它也允许在列表中进行动态内存分配、增加、搜索、排序各项。System.Collections.Generic命名空间中的类List的用法非常类似于System.Collections命名空间中的ArrayList类,这个类实现了IList、ICollection和IEnumerable接口。对于新的应用程序,通常可以使用泛型类List

替代非泛型类ArrayList,而且ArrayList类的方法与List

非常相似,所以本节将只讨论如何使用List

类。1. 创建列表调用默认的构造函数就可以创建对象列表。在泛型类List

中,必须在声明中为列表的值指定类型。下面的代码说明了如何声明一个包含int和string的列表。

List

intList = new List

();

List

strList =new List

();使用默认的构造函数创建一个空列表。元素添加到列表中后,列表的容量就会扩大为可接纳4个元素。如果添加了第5个元素,列表的大小就重新设置为包含8个元素。如果8个元素还不够,列表的大小就重新设置为16。每次都会将列表的容量重新设置为原来的2倍。为节省时间,如果事先知道列表中元素的个数,就可以用构造函数定义其容量。下面的代码创建了一个容量为10个元素的集合。如果该容量不足以容纳要添加的元素,就把集合的大小重新设置为20或者40,每次都是原来的2倍。

List

intList = new List

(10);使用Capacity属性可以获取和设置集合的容量。

intList.Capacity = 20;容量与集合中元素的个数不同。集合中元素的个数可以用Count属性读取。当然,容量总是大于或等于元素个数。只要不把元素添加到列表中,元素个数就是0。其格式如下: 

Console.WriteLine(intList.Count);如果已经将元素添加到列表中,且不希望添加更多的元素,就可以调用TrimExcess()方法,去除不需要的容量。但是,重新定位是需要时间的,所以如果元素个数超过了容量的90%,TrimExcess()方法将什么也不做。其格式如下: 

intList.TrimExcess();2. 添加元素使用Add()方法可以给列表添加元素。Add()方法将对象添加到列表的结尾处。例如: 

List

intList = new List

();

intList.Add(1);

intList.Add(2);

List

strList =new List

();

strList.Add("one");

strList.Add("two");使用List

类的AddRange()方法可以一次给集合添加多个元素。AddRange()方法的参数是IEnumerable

类型对象,所以也可以传送一个数组。例如: 

strList.AddRange(new string[ ]{"one","two","three"});3. 插入元素使用Insert()方法可以在列表的指定位置插入元素,位置从0开始索引。例如: 

intList.Insert(3,6);InsertRange()方法提供了插入大量元素的容量,类似于前面的AddRange()方法。如果索引集大于集合中的元素个数,就抛出ArgumentOutOfRangeException类型的异常。4. 访问元素执行了IList和IList接口的所有类都提供了一个索引器,所以可以使用索引器,通过传送元素号来访问元素。第一个元素可以用索引值0来访问。例如,指定intList[3],可以访问列表intList中的第4个元素: 

intnum = intList[3];可以用Count属性确定元素个数,再使用for循环迭代集合中的每个元素,使用索引器访问每一项。例如: 

for (int i=0; i

{

Console.WriteLine(intList[i]);

}List执行了接口IEnumerable,所以也可以使用foreach语句迭代集合中的元素。编译器解析foreach语句时,利用了接口IEnumerable和IEnumerator。例如: 

foreach (int i in intList)

{

Console.WriteLine(i);

}5. 删除元素删除元素时,可以利用索引或传送要删除的元素。下列代码把3传送给RemoveAt(),删除第4个元素: 

intList. RemoveAt(3);也可以直接把对象传送给Remove()方法,删除这个元素。例如: 

intList.Remove(3);//删除列表中元素3RemoveRange()方法可以从集合中删除许多元素。它的第一个参数指定了开始删除的元素索引,第二个参数指定了要删除的元素个数。例如: 

int index = 3;

int count = 5;

intList. RemoveRange(index, count);要删除集合中的所有元素,可以使用ICollection

接口定义的Clear()方法。6. 搜索有不同的方式在集合中搜索元素。可以获得要查找的元素的索引,或者搜索元素本身。可以使用的方法有IndexOf()、LastIndexOf()、FindIndex()、FindLastIndex()、Find()和FindLast()。如果只检查元素是否存在,List

类提供了Exists()方法。IndexOf()方法需要将一个对象作为参数,如果在集合中找到该元素,这个方法就返回该元素的索引。如果没有找到该元素,就返回-1。IndexOf()方法使用IEquatable接口来比较元素。例如: 

int index= intList. IndexOf(3);使用IndexOf()方法,还可以指定不需要搜索整个集合,但必须指定从哪个索引开始搜索以及要搜索的元素个数。3.3.3.3队列队列是其元素以先进先出(FIFO)的方式来处理的集合。先放在队列中的元素会先读取。队列的例子有在机场排的队、人力资源部中等待处理求职信的队列、打印队列中等待处理的打印任务、以循环方式等待CPU处理的线程等。另外,还常常有元素根据其优先级来处理的队列。例如,在机场的队列中,商务舱乘客的处理要优先于经济舱的乘客。这里可以使用多个队列,一个队列对应一个优先级。在机场,这是很常见的,因为商务舱乘客和经济舱乘客有不同的登记队列。打印队列和线程也是这样。可以为一组队列建立一个数组,数组中的一项代表一个优先级。在每个数组项中,都有一个队列,其处理按照FIFO的方式进行。在.NET的System.Collections命名空间中有非泛型类Queue,在System.Collections.Generic命名空间中有泛型类Queue

。这两个类的功能非常类似,但泛型类是强类型化的,定义了类型T,而非泛型类基于Object类型。在内部,Queue

类使用T类型的数组,这类似于List

类型。另一个类似之处是它们都执行ICollection和IEnumerable接口。Queue类执行了ICollection、IEnumerable和ICloneable接口。Queue

类执行了IEnumerable和ICloneable接口。Queue

泛型类没有执行泛型接口ICollection

,因为这个接口用Add()和Remove()方法定义了在集合中添加和删除元素的方法。队列与列表的主要区别是队列没有执行IList接口,所以不能用索引器访问队列。队列只允许添加元素,该元素会放在队列的尾部[使用Enqueue()方法],从队列的头部获取元素[使用Dequeue()方法]。图38显示了队列的元素。Enqueue()方法在队列的一端添加元素,Dequeue()方法在队列的另一端读取和删除元素。用Dequeue()方法读取元素,将同时从队列中删除该元素。再调用一次Dequeue()方法,会删除队列中的下一项。

图38队列

Queue和Queue

类的方法如表34所示。

表34Queue和Queue

类的方法

成员说明

Enqueue()在队列一端添加一个元素Dequeue()在队列的头部读取和删除一个元素。如果在调用Dequeue()方法时,队列中不再有元素,就抛出InvalidOperationException异常Peek()在队列的头部读取一个元素,但不删除它Count返回队列中的元素个数TrimExcess()重新设置队列的容量。Dequeue()方法从队列中删除元素,但不会重新设置队列的容量。要从队列的头部去除空元素,应使用TrimExcess()方法Contains()确定某个元素是否在队列中,如果是,就返回trueCopyTo()把元素从队列复制到一个已有的数组中ToArray()ToArray()方法返回一个包含队列元素的新数组下列代码演示了Queue

类的基本用法。

Queue

numbers = new Queue

(); //实例化队列对象

//向队列中添加元素

numbers.Enqueue("one");

numbers.Enqueue("two");

numbers.Enqueue("three");

numbers.Enqueue("four");

numbers.Enqueue("five");

//遍历队列中的元素

foreach( string number in numbers )

{

Console.Write("{0} ",number);

}

//调用队列方法

Console.WriteLine("\nDequeuing {0}", numbers.Dequeue());

Console.WriteLine("Peek at next item to dequeue: {0}", numbers.Peek());

Console.WriteLine("Dequeuing {0}", numbers.Dequeue());上面代码会产生如下的输出结果: 

one two three four five

Dequeuing one

Peek at next item to dequeue: two

Dequeuing wo3.3.4拓展与提高借助网络资源,了解C#中其他集合类的用法,列表比较各种集合类的特点,提高数据处理的能力。3.4知识点提炼(1) C#提供了能够存储多个相同类型变量的集合,这种集合就是数组。数组是同一数据类型的一组值,它属于引用类型。(2) 数组在使用之前必须先定义。一个数组的定义必须包含元素类型、数组维数和每个维数的上下限。(3) 数组在使用之前必须进行初始化。初始化数组有两种方法: 动态初始化和静态初始化。动态初始化需要借助new关键字,为数组元素分配内存空间,并为数组元素赋初值。静态初始化数组时,必须与数组定义结合在一起,否则会出错。(4) C#中的字符包括数字字符、英文字母、标点符号等,C#提供的字符类型按照国际上公认的标准,采用Unicode字符集。要得到字符的类型,可以使用System.Char命名空间中的内置静态方法。(5) C#语言中,string类型是引用类型,其表示零或更多个Unicode字符组成的序列。利用字符串类的方法可以实现对字符串的处理操作。(6) 可变字符串类StringBuilder创建了一个字符串缓冲区,允许重新分配个别字符,这些字符是内置字符串数据类型所不支持的。(7) 集合提供一种动态对数据分组的方法。.NET Framework提供了常用集合操作类。

















































.NET应用程序开发技术与项目实践(C#版) pdf下载声明

本pdf资料下载仅供个人学习和研究使用,不能用于商业用途,请在下载后24小时内删除。如果喜欢,请购买正版

pdf下载地址

版权归出版社和作者所有,下载链接已删除。如果喜欢,请购买正版!

链接地址:.NET应用程序开发技术与项目实践(C#版)