描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302447733丛书名: 21世纪高等学校计算机应用技术规划教材
全书共10章,分别介绍Web基础知识、ASP.NET概述、C#程序设计基础、ASP.NET控件、ASP.NET内置对象、数据库基础知识、ASP.NET数据库编程、用户界面设计、教务管理系统实训和强大的LINQ查询等内容。每章都配有本章小结和习题,以方便读者巩固所学知识。特别地,在应用性较强的章中,多加一节具有实际应用的示例,便于读者更好地将理论与实践相结合。本书还专门设置了一章小型案例系统实训,以“教务管理系统”为例,通过系统分析和设计、数据库设计、网站设计和详细设计把所介绍的知识融合应用并把软件的开发流程呈现给用户,突出了系统性和实践性,使读者达到学以致用的目的。
本书适合作为普通高等院校计算机及其相关专业的教材或参考书,也可作为初、中级网站开发者及动态网页设计者或其他业余爱好者的参考用书。
目录
第1章Web基础知识
1.1Web技术基础
1.2Web结构
1.3网页构成技术——HTML
1.4静态网页和动态网页
1.4.1静态网页
1.4.2动态网页
1.5常见的网络程序设计语言
本章小结
习题
第2章ASP.NET概述
2.1.NET Framework简介
2.2ASP.NET简介
2.3ASP.NET运行及开发环境
2.3.1IIS7.5的安装
2.3.2IIS7.5的配置
2.3.3Visual Studio 2012集成开发环境
2.4个ASP.NET程序
2.4.1创建Web项目
2.4.2Web项目的构成
2.4.3创建ASP.NET网页
2.5创建ASP.NET程序的步骤
本章小结
习题
第3章C#程序设计基础
3.1C#基础语法
3.1.1数据类型和常量、变量
3.1.2运算符和表达式
3.2流程控制语句
3.2.1选择语句
3.2.2循环语句
3.3常用的.NET框架类
3.3.1DateTime类
3.3.2Math类
3.3.3Random类
3.4C#面向对象编程
3.4.1类与对象
3.4.2类的成员
3.4.3继承
本章小结
习题
第4章ASP.NET控件
4.1ASP.NET控件概述
4.1.1HTML控件
4.1.2HTML服务器控件
4.1.3Web服务器控件
4.2常用的Web控件
4.2.1标签控件
4.2.2文本框控件
4.2.3命令类控件
4.2.4图像控件
4.2.5超链接控件
4.2.6选择类控件
4.3其他常用控件
4.3.1容器控件
4.3.2日历控件
4.3.3文件上传控件
4.4数据验证控件
4.4.1RequiredFieldValidator非空验证
4.4.2RangeValidator范围验证
4.4.3CompareValidator比较验证
4.4.4RegularExpressionValidator规则验证
4.4.5CustomValidator自定义验证
4.4.6ValidatorSummary验证总结
4.5用户控件
4.5.1创建用户控件
4.5.2添加用户控件
4.6Web服务器控件的综合应用
本章小结
习题
第5章ASP.NET内置对象
5.1对象概述
5.2Page对象
5.2.1Page对象简介
5.2.2Page对象生命周期
5.2.3利用Page对象进行页面初始化
5.3Response对象
5.3.1Response对象简介
5.3.2Write方法和WriteFile方法
5.3.3Redirect方法
5.3.4BufferOutput属性
5.3.5End方法
5.3.6Flush方法和Clear方法
5.4Request对象
5.4.1Request对象简介
5.4.2获取用户提交的信息
5.4.3获取客户端浏览器信息
5.5Cookie对象
5.5.1Cookie对象简介
5.5.2读写Cookie
5.6Session对象
5.6.1Session对象简介
5.6.2利用Session对象存储信息
5.6.3TimeOut属性
5.6.4Abandon方法
5.7Application对象
5.7.1Application对象简介
5.7.2利用Application对象存储信息
5.7.3Global.asax文件
5.8Server对象
5.8.1Server对象简介
5.8.2ScriptTimeout属性
5.8.3HTMLEncode方法
5.8.4UrlEncode方法
5.8.5MapPath方法
5.8.6Execute方法和Transfer方法
5.9内置对象的综合应用
本章小结
习题
第6章数据库基础知识
6.1数据库概述
6.1.1数据库的基本概念
6.1.2数据管理技术的产生和发展
6.1.3数据模型
6.1.4常用的数据库管理系统
6.2创建Access数据库
6.2.1启动Access并创建数据库
6.2.2创建数据表并输入数据
6.2.3数据表的查询操作
6.3SQL语言
6.3.1SQL语言常用命令
6.3.2SELECT语句
6.3.3INSERT语句
6.3.4UPDATE语句
6.3.5DELETE语句
本章小结
习题
第7章ASP.NET数据库编程
7.1数据源控件
7.2数据绑定控件
7.2.1添加数据源控件
7.2.2添加GridView控件
7.2.3GridView分页、排序、列标题设置
7.2.4GridView选择、编辑、删除数据
7.2.5GridView超链接字段
7.3ADO.NET方式访问数据库
7.3.1ADO.NET概述
7.3.2ADO.NET数据访问流程
7.3.3常用ADO.NET对象的使用
7.3.4事务处理
7.4访问数据库的高级操作
7.4.1利用ADO.NET访问两种数据之间的转换
7.4.2在Web.config中配置数据库连接
7.4.3DataSet对象的高级应用
7.4.4GridView控件的高级应用
7.4.5其他数据绑定控件
7.5数据库访问技术的综合应用
本章小结
习题
第8章用户界面设计
8.1母版页
8.1.1母版页的基础知识
8.1.2母版页的创建
8.1.3母版页的使用
8.2站点导航
8.2.1站点地图
8.2.2站点导航控件
8.3主题
8.3.1主题概述
8.3.2创建主题
8.3.3应用主题
8.4用户界面设计的综合应用
本章小结
习题
第9章教务管理系统实训
9.1系统分析与系统设计
9.1.1系统分析
9.1.2系统设计
9.1.3系统结构图
9.1.4系统流程图
9.2数据库设计
9.3网站设计
9.3.1网站结构图
9.3.2页面功能
9.3.3站点导航设计
9.3.4母版设计
9.4详细设计
9.4.1数据库的建立
9.4.2公共类的编写
9.4.3配置文件Web.config的设置
9.4.4首页页面
9.4.5管理员页面
9.4.6教师页面
9.4.7学生页面
9.5网站发布
本章小结
习题
第10章强大的LINQ查询
10.1认识LINQ
10.2LINQ语法基础
10.3LINQ to Object
10.4LINQ to DataSet
本章小结
习题
参考文献
目前,Web应用程序设计一般都使用ASP.NET、JSP和PHP。ASP.NET由Microsoft公司提出,易学易用、开发效率高,可配合任何一种.NET语言进行开发。JSP需配合使用Java语言。PHP的优点是开源,缺点是缺乏大公司的支持。JSP和PHP较ASP.NET要难学。实际上,国内外越来越多的软件公司已应用ASP.NET技术进行Web应用程序开发。本书基于Visual Studio 2012开发环境,以C#为脚本,通过通俗易懂的语言和丰富典型的实例,由浅入深、循序渐进地讲述使用ASP.NET技术进行Web应用程序开发的方法。书中实例全部出自编者实际教学和工作过程中所采用的实例,都在Visual Studio 2012上编译通过,以方便读者自学理解。书中源程序注释清晰明了,方便读者自行修改和升级。全书共10章,分别介绍Web基础知识、ASP.NET概述、C#程序设计基础、ASP.NET控件、ASP.NET内置对象、数据库基础知识、ASP.NET数据库编程、用户界面设计、教务管理系统实训和强大的LINQ查询等内容。每章都配有本章小结和习题,以方便读者巩固所学知识。与市场上其他ASP.NET方面的图书相比,本书具有以下特点。1. 循序渐进,轻松上手本书是一线教师多年教学和实践的总结,编者长期从事.NET方向程序设计的教学和研究工作,对教学的难点和重点十分清楚,对学生的学习误区也有一定的了解。本书力求符合学生学习心理和学习习惯,合理安排各章节,以实例由浅入深地阐述如何利用ASP.NET技术(以C#语言为基础)进行Web应用程序的开发,让学生能够逐步体会并掌握利用.NET框架进行Web开发的精髓。2. 实例丰富,贴近实际本书每部分内容都有实例,简单易懂,帮助读者理解相关知识内容。特别地,在应用性较强的章节中,多加一节具有实际应用的示例,便于读者更好地将理论与实践相结合。3. 图文并茂,步骤详细本书讲解技术和例题时,图文并茂,步骤详细。读者只需按照步骤操作,就可以体会编程带来的乐趣和成就感。4. 完整案例,融会贯通本书专门设置了一个完整、实用的小型案例系统实训作为独立的一章,以“教务管理系统”为例,通过系统分析和设计、数据库设计、网站设计和详细设计把所介绍的知识融合应用并把软件的开发流程呈现给用户,突出了系统性和实践性,使读者达到学以致用的目的。本书可作为普通高等院校计算机及其相关专业的教材或参考书,也可作为初、中级网站开发者及动态网页设计者或其他业余爱好者的参考用书。清华大学出版社的网站(http://www.tup.com.cn)上提供本书的多媒体课件和所有例题源代码,课件等资源下载及本书使用的相关问题,请联系[email protected]。本书由哈尔滨金融学院张玉芬担任主编,由哈尔滨金融学院赵立波、李康乐担任副主编,哈尔滨工程大学杨萌和中国电子科技集团公司第四十九研究所李冰冰参编。其中,第1章由李冰冰编写,第6章和第7章由张玉芬编写,第3章、第5章和第10章由赵立波编写,第2章、第4章和第8章由李康乐编写,第9章由杨萌编写,全书由张玉芬统稿。由于时间仓促,编者经验有限,书中难免会有疏漏和不足之处,敬请读者和同行们予以批评指正,使本书得以改进和完善。编者联系邮箱[email protected]。编者2016年9月
ASP.NET的页面与业务逻辑代码是分开的,业务逻辑代码是用面向对象语言编写的,可以用.NET系列中的任一种语言开发,包括C 、C#、J#、Visual Basic等。在本书中采用的是C#语言,在本章中主要介绍语法基础。3.1.1数据类型和常量、变量1. 数据类型
按数据的存储方式划分,C#的数据类型可分为值类型和引用类型。值类型在其内存空间中包含实际的数据,而引用类型中存储的是一个指针,该指针指向存储数据的内存位置。值类型的内存开销小,访问速度快,但是缺乏面向对象的特征; 引用类型的内存开销大(在堆上分配内存),访问速度稍慢。值类型包括整数类型、实数类型、字符类型、布尔类型、枚举类型和结构类型。和值类型相比,引用类型不存储它们所代表的实际数据,但它们存储实际数据的引用。一个具有引用类型的数据并不驻留在栈内存中,而是存储于堆内存中。在堆内存中分配内存空间直接存储所包含的值,而在栈内存中存放定位到存储具体值的索引位置编号。当访问一个具有引用类型的数据时,需要到栈内存中检查变量的内容,而该内容指向堆中的一个实际数据。C#的引用类型包括类、接口、委托和字符串等。2. 类型转换在编程工作中,有很多时候需要不同类型的量相互转换,例如,用户在页面上输入的所有内容均为字符串类型,但是程序却想用某些内容做数学运算,此时需要在使用输入内容之前做一个类型转换。1) 隐式转换隐式转换又称为自动类型转换,若两种变量的类型是兼容的或者目标类型的取值范围大于原类型时,就可以使用隐式转换。2) 显式类型转换显式类型转换又称为强制类型转换,该方式需要用户明确地指定转换的目标类型,该类型转换的一般形式为:
(类型标识符)表达式
例如:
int i = (int)7.256;//将float类型的7.256转换为int类型,并赋值于int类型变量i
3) 使用Parse()方法进行数据类型的转换每个数值数据类型都包含一个Parse()方法,它可以将特定格式的字符串转换为对应的数值类型,其使用格式为:
数值类型名称.Parse(字符串型表达式)
例如:
string s1 =”30″,s2=”3.9″;
int i = int.Parse(s1);//字符串符合整型格式,转换成功
float j = float.Parse(s2); //字符串符合浮点格式,转换成功
int k = float.Parse(s2);//字符串不符合整型格式,出错
4) 使用ToString()方法进行数据类型的转换ToString()方法可将其他数据类型的变量值转换为字符串类型,其使用格式为:
变量名称.ToString( )
例如:
int i = 69;
string s = i.ToString( );// s = “69”
5) 使用Convert类的方法进行数据类型的转换在实际编程中,基本类型之间的相互转换是一种非常常见的操作。System.Convert类就是为这个目的而设计的,其功能是将一种基本数据类型转换为另一种基本数据类型。Convert类的所有方法都是静态方法,如表31所示,其使用格式为:
Convert.方法名(原始数据)
表31Convert类的常用方法
名称主 要 功 能
ToBoolean()将指定的值转换为等效的布尔值ToByte()将指定的值转换为8位无符号整数ToChar()将指定的值转换为Unicode字符续表
名称主 要 功 能
ToDateTime()将指定的值转换为DateTime类型ToDecimal()将指定的值转换为Decimal数字ToDouble()将指定的值转换为双精度浮点数字ToInt16()将指定的值转换为16位有符号整数ToInt32()将指定的值转换为32位有符号整数ToInt64()将指定的值转换为64位有符号整数ToSByte()将指定的值转换为8位有符号整数ToSingle()将指定的值转换为单精度浮点数字ToUInt16()将指定的值转换为16位无符号整数ToUInt32()将指定的值转换为32位无符号整数ToUInt64()将指定的值转换为64位无符号整数ToString()将指定的值转换为与其等效的String形式
例如:
string s = “97”;
int n = Convert.ToInt32(s);// n = 97
char c = Convert.ToChar(n); // ASCII码为97的字符是a,即c = ‘a’
string str=”123456789.123456789″;
decimal dec = Convert.ToDecimal(str);//dec=123456789.123456789
double d1 = Convert.ToDouble(dec); //d1=123456789.123457
int i = Convert.ToInt32(d1);//i=123456789
3. 常量在程序运行过程中,其值保持不变的量称为常量。常量可分为直接常量和符号常量两种形式。1) 直接常量所谓直接常量,就是在程序中直接给出的数据值。在C#语言中,直接常量包括整型常量、浮点型常量、小数型常量、字符型常量、字符串常量和布尔型常量。(1) 整型常量。例如,5、5U、5L。(2) 浮点型常量。例如,3f、3d。需要注意的是,以小数形式直接书写而未加标记时,系统将自动解释成双精度浮点型常量。例如,9.0即为双精度浮点型常量。(3) 小数型常量。在C#语言中,小数型常量的后面必须添加m或M标记,否则就会被解释成标准的浮点型数据,如7.0M。(4) 字符型常量。字符型常量是一个标准的Unicode字符,用来表示字符数据常量时,共有以下几种不同的表示方式。① 用单引号将一个字符包括起来,如’R’、’8’、’李’。② 用原来的数值编码来表示字符数据常量,如’A’是65,’b’是98。虽然char型数据的表示形式与ushort(无符号短整型)相同,但ushort与char意义不同,ushort代表的是数值本身,而char代表的则是一个字符。例如,
char m = ‘A’;
int k = m 32;//k的值为97
③ C#提供了转义符,用来在程序中指代特殊的控制字符,常用的转义字符如表32所示。
表32C#常用转义字符
转 义 序 列产生的字符字符的Unicode值
\’单引号0x0027\”双引号0x0022\\反斜杠0x005c\0空字符0x0000\a响铃符0x0007\b退格符0x0008\f换页符0x000c\n换行符0x000a\r回车符0x000d\t水平制表符0x0009\v垂直制表符0x000b
(5) 字符串常量。字符串常量表示若干个Unicode字符组成的字符序列,使用两个双引号来标记,如”book”、”123″、”中国”。(6) 布尔型常量。布尔型常量只有两个: 一个是true,表示逻辑真; 另一个是false,表示逻辑假。2) 符号常量符号常量使用const关键字定义,格式为:
const 类型名称常量名 = 常量表达式;
“常量表达式”不能包含变量、函数等值会发生变化的内容,可以包含其他已定义常量。如果在程序中非常频繁地使用某一常量,可以将其定义为符号常量,例如:
const double PI = 3.1415926;
const int Months = 12,Weeks = 52,Days = 365;
4. 变量在程序运行过程中,其值可以改变的量称为变量。变量可以用来保存从外部或内部接收的数据,也可以保存在处理过程中产生的中间结果或终结果。在C#语言中,每一个变量都必须具有变量名、存储空间和取值等属性。【例31】编写一个网页,在文本框中输入圆的半径,单击“计算”按钮,显示圆的面积。具体实现步骤如下。(1) 新建一个网站,在资源管理器中右击网站,然后在弹出的快捷菜单选择“添加/Web窗体”选项,在弹出的指定名称对话框中给网页命名。(2) 在网页中添加Label控件、TextBox控件、Button控件。页面设计如图31所示。
图31例31设计界面
(3) 在网页设计界面,选中Button1,在属性窗口中选中闪电标志,双击Click事件,为它添加单击事件代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
double s,r;
const double PI = 3.14159;
r = double.Parse(TextBox1.Text);
s = PI * r * r;
Label1.Text = “圆的面积是: ” s.ToString();
}
程序运行结果如图32所示。
图32圆面积的运行结果
Windows的窗体程序都是事件驱动程序。当用户使用鼠标或键盘或其他输入设备做一个动作时,对于程序来说都是一个事件。例如,单击按钮,对于程序来说是发生了一个单击事件。在C#语言中,每个控件都有已经准备好的若干事件框架,编程人员按需要决定是否响应这些事件。响应的方式是选中某一控件,在属性窗口单击事件按钮,找到对应事件,双击即生成了事件处理方法,在事件处理方法中输入处理代码即可。如果某一事件对于这个控件来说是经常发生的,那么这个事件就是它的默认事件,对于默认事件,可以直接在设计界面双击此控件,直接进入事件代码页面,并生成事件方法。例如,对于按钮来说,单击是常发生的,所以例31也可以双击按钮响应单击事件。变量的类型包括整数类型、实数类型、单精度类型、双精度类型、字符类型、字符串类型、布尔类型、枚举类型和结构类型。它们的类型标识符分别为int、decimal、float、double、char、string、bool、struct、enum。除此之外,还有数组。变量的命名规则是: 变量名只能由字母、数字和下画线组成,不能包含空格、标点符号、运算符等其他符号。不能以数字开头。还要注意C#严格区分大小写,name和Name对于C#是完全不同的两个变量。1) 变量的声明变量的声明格式为:
类型标识符 变量列表;
例如:
int x,y,z;//合法
int 3old;//不合法,以数字开头
float struct; //不合法,与关键字名称相同
float Main;//不合法,与函数名称相同
数组变量的声明格式为:
类型标识符[] 数组名 = new 类型标识符[数组长度];
例如:
int[] arr = new int[5];
2) 变量的赋值在C#语言中,变量必须赋值后才能引用。为变量赋值,一般使用赋值号“=”。例如:
char ch;//声明一个字符型变量
ch = ‘m’; //为字符型变量ch赋值
int a,b,c;
a = b = c = 0;//同时为多个变量赋相同的值
bool b1 = true,b2 = false;//声明布尔型变量b1和b2,同时为其赋值
数组的赋值可以在声明的时进行初始化,例如:
int[] arr = new int[5]{1,2,3,4,5};
如果在声明的同时进行初始化,就可以省略“new类型标识符[数组长度]”这部分,例如:
int[] arr = {1,2,3,4,5};
如果不在声明数组的同时进行初始化,数组必须按下标一个一个进行赋值或引用。
int[] arr = new int[5];
arr[0]=1;
arr[1]= arr[0] 1;
3.1.2运算符和表达式运算符用于对操作数进行特定的运算,而表达式则是运算符和相应的操作数按照一定的规则连接而成的式子。1. 算术运算符和算术表达式算术运算符有一元运算符与二元运算符。一元运算符包括 (取正)、-(取负)、 (自增)、–(自减); 二元运算符包括 (加)、-(减)、*(乘)、/(除)、%(求余)。2. 字符串运算符与字符串表达式字符串运算符只有一个,即“ ”运算符,表示将两个字符串连接起来。例如:
string s1 = “计算机” “编程”;// s1的值为”计算机编程”
“ ”运算符还可以将字符串型数据与一个或多个字符型数据连接在一起,例如:
string s2 = ‘A’ “bcd” ‘E’;// s2的值为”AbcdE”
3. 关系运算符与关系表达式关系运算又称为比较运算,实际上是逻辑运算的一种,关系表达式的返回值总是布尔值。关系运算符用于对两个操作数进行比较,以判断两个操作数之间的关系。C#中定义的比较操作符有= = (等于)、!=(不等于)、(大于)、<=(小于或等于)、>=(大于或等于)。关系表达式的运算结果只能是布尔型值,要么是true,要么是false。4. 逻辑运算符与逻辑表达式C#语言提供了4类逻辑运算符: &&(条件与)或&(逻辑与)、||(条件或)或|(逻辑或)、!(逻辑非)和^(逻辑异或)。其中,&&、&、||、|和^都是二元操作符,而!为一元操作符。它们的操作数都是布尔类型的值或表达式。5. 赋值运算符赋值运算符“=”称为“简单赋值运算符”,它与其他算术运算符结合在一起可组成“复合赋值运算符”,如“*=”“/=”“%=”“ =”“-=”等。6. 条件运算符条件运算符由“?”和“:”组成,其一般格式为:
关系表达式?表达式1: 表达式2
条件表达式在运算时,首先计算“关系表达式”的值,如果为true,则运算结果为“表达式1”的值,否则运算结果为“表达式2”的值。例如:
int x = 50 , y = 80 , m;
m = x > y ? x * 5 : y 20 ;//m的值为100
条件表达式也可以嵌套使用,从而实现多分支的选择判断。这些常用运算符从高到低的优先级顺序如表33所示。
表33运算符的优先级
优先级类别运算符
1初级运算符()2一元运算符 (正)-(负)!~ –3乘除运算符*/%4加减运算符 -5位运算符<<>>6关系运算符<><=>=7关系运算符==!=8逻辑与&9逻辑异或^10逻辑或|11条件与&&12条件或||13条件运算符? :14赋值运算符=*=/=%= =-=<<=>>=&=^=|=
3.2流程控制语句
虽然C#语言是完全面向对象的语言,但在局部的语句块内,仍然要使用结构化程序设计的方法,用控制结构来控制程序的执行流程。结构化程序设计有3种基本控制结构,分别是顺序结构、选择结构和循环结构。3.2.1选择语句常用的条件语句有如下几种。1. if语句if语句是基于布尔表达式的值来判定是否执行后面的内嵌的语句块,其语法形式有3种,分别为:
if(表达式)
{
语句块;
}
或者
if(表达式)
{
语句块1;
}
else
{
语句块2;
}
或者
if(表达式1)
{
语句块1
}
else if(表达式2)
{
语句块2
}
else if(表达式m)
{
语句块m
}
else
{
语句n
}
【例32】输入一个整数,求值。程序分析如下。如果是负数,取反; 否则,值是这个数本身。网页设计如图33所示。
图33例32网页设计
程序代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
int x;
x = Convert.ToInt32(TextBox1.Text);
if (x < 0)
{
x = -x;
}
Label1.Text=”|” TextBox1.Text “|=” x;
}
网页运行结果如图34所示。
图34求值程序运行结果
【例33】检查输入字符是否为大写字符、小写字符或数字; 否则,该输入字符是其他字符。char类型有判断字符是何种类型的方法,分别是char.IsUpper(字符)、char.IsLower(字符)、char.IsDigit(字符),返回值为布尔类型。界面设计与例31和例32相似,为了美观,我们将按钮上的文本更改为“判断字符”。同样地,代码编写在按钮的单击事件中。
protected void Button1_Click(object sender, EventArgs e)
{
char c = Convert.ToChar(TextBox1.Text);
if (char.IsUpper(c))
Label1.Text = c.ToString() “是大写字符”;
else if (char.IsLower(c))
Label1.Text = c.ToString() “是小写字符”;
else if (char.IsDigit(c))
Label1.Text = c.ToString() “是数字字符”;
else
Label1.Text = c.ToString() “是其他字符”;
}
执行上述程序的运行结果如图35所示。
图35数字字符程序运行结果
2. switch语句当判定的条件有多个时,如果使用ifelse语句将会让程序变得难以阅读。而开关语句(switch语句)提供一个更为简洁的语法,以便处理复杂的条件判定。switch语句的一般格式如下:
switch(表达式)
{
case 常量表达式1;
语句1;
break;
case 常量表达式2;
语句2;
break;
…
case 常量表达式n;
语句n;
break;
[default:
语句n 1;
break;]
}
执行过程如下。(1) 首先计算switch后面的表达式的值。(2) 如果表达式的值等于“case常量表达式1”中常量表达式1的值,则执行语句1,然后通过break语句退出switch结构,执行位于整个switch结构后面的语句; 如果表达式的值不等于“case常量表达式1”中常量表达式1的值,则判定表达式的值是否等于常量表达式2的值,以此类推,直到后一个语句。(3) 如果switch后的表达式与任何一个case后的常量表达式的值都不相等,若有default语句,则执行default语句后面的语句n 1,执行完毕后退出switch结构,然后执行位于整个switch结构后面的语句; 若无default语句则退出switch结构,执行位于整个switch结构后面的语句。【例34】使用switch语句将学生成绩转换为等级输出。界面设计参照例31。单击事件代码如下:
protected void Button1_Click(object sender, EventArgs e)
{
int Score;
Score = Convert.ToInt32(TextBox1.Text);
int temp = Score / 10;
switch (temp)
{
case 10:
case 9:
Label1.Text = “A等级”;
break;
case 8:
Label1.Text = “B等级”;
break;
case 7:
Label1.Text = “C等级”;
break;
case 6:
Label1.Text = “D等级”;
break;
default:
Label1.Text = “E等级”;
break;
}
}
执行上述程序的运行结果如图36所示。
图36switch语句的应用运行结果
3.2.2循环语句循环结构是在给定条件成立时,反复执行某程序段,直到条件不成立为止。给定的条件称为循环条件,反复执行的程序段称为循环体。1. while循环while语句先计算表达式的值,值为true则执行循环体; 反复执行上述操作,直到表达式的值为false时止。语法如下:
while (表达式)
{
循环体
}
执行while语句的步骤如下。(1) 执行while后面括号中的表达式; (2) 当表达式的运算结果为true,则执行循环体,否则跳过步骤(3),直接执行步骤(4)。(3) 反复执行(1)、(2)步骤,直到表达式的运算结果为false时止。(4) 执行while语句块后面的代码。2. dowhile循环dowhile语句与while语句功能相似,但和while语句不同的是,dowhile语句的判定条件在后面,这和while语句不同。dowhile循环不论条件表达式的值是什么,dowhile循环都至少要执行一次。语法如下:
do{
循环体
}while(表达式);
说明: 当循环执行到do语句后,先执行循环体语句; 执行完循环体语句后,再对while语句括号中的条件表达式进行判定。若表达式的值为true,则转向do语句继续执行循环体语句; 若表达式的值为false,则退出循环,执行程序的下一条语句。3. for循环for语句和while语句一样,也是一种循环语句,用来重复执行一段代码,两个循环语句的区别就是使用方法不同。for语句的使用语法如下:
for (表达式1; 表达式2; 表达3)
{
循环体
}
执行for语句的步骤如下。(1) 计算表达式1的值。(2) 计算表达式2的值,若值为true,则执行循环体一次,否则跳出循环。(3) 计算表达式3的值,转回第(2)步重复执行【例35】计算1 2 3 … 100的和。新建网页之后,选择代码文件,在代码文件中添加如下代码:
protected void Page_Load(object sender, EventArgs e)
{
int i = 1, sum = 0;
while (i <= 100)
{
sum = i;
i ;
}
Response.Write(“1 2 3 … 100的和为: ” sum);
}
Page_Load事件是整个页面加载过程中执行的事件,Response.Write()方法是向网页中输出内容。因此网页被执行后,页面中输出内容为:
1 2 3 … 100的和为: 5050
4. foreach语句foreach语句对于处理数组及集合等数据类型特别简便。foreach语句用于列举集合中的每一个元素,并且通过执行循环体对每一个元素进行操作。foreach语句只能对集合中的元素进行循环操作。foreach语句的一般语法格式如下:
foreach(数据类型标识符 迭代变量 in 表达式)
{
循环体;
}
【例36】用foreach输出数组的值。在新建网页的代码文件中添加如下代码:
protected void Page_Load(object sender, EventArgs e)
{
int[] arr = new int[5] { 1, 2, 3, 4, 5 };
foreach (int m in arr)
{
Response.Write(m “,”);
}
}
网页运行后,将在页面中显示数组中的内容。代码中的语句说明如下。(1) Response.Wrtie()方法的功能是向网页输出内容。参数需要指明输出的字符串内容,同时字符串中可以包含HTML语言中的标识。(2) foreach语句中的循环变量是由数据类型和标识符声明的,循环变量在整个foreach语句范围内有效; foreach语句中的表达式必须是集合类型,若该集合的元素类型与循环变量类型不一致,必须有一个显示定义的从集合中元素类型到循环变量元素类型的显示转换。在foreach语句执行过程中,循环变量就代表当前循环所执行的集合中的元素。每执行一次循环体,循环变量就依次将集合中的一个元素代入其中,直到把集合中的元素处理完毕,跳出foreach循环,转而执行程序的下一条语句。5. break和continue在C#语言中可以用跳转语句来改变程序的执行顺序。在程序中采用跳转语句,可以避免可能出现的死循环。C#语言中的跳转语句有break语句、continue语句、return语句和goto语句等。break语句常用于switch、while、dowhile、for或foreach等语句中。在switch语句中,break用来使程序流程跳出switch语句,继续执行switch后面的语句; 在循环语句中,break用来从当前所在的循环内跳出。break语句的一般语法格式如下:
break;
break语句通常和if语句配合,以便实现某种条件满足时从循环体内跳出的目的。在多重循环中,则是跳出break所在的循环。continue语句用于while、dowhile、for或foreach循环语句中。在循环语句的循环体中,当程序执行到continue语句时,将结束本次循环,即跳过循环体下面还没有执行的语句,并进行下一次表达式的计算与判定,以决定是否执行下一次循环。continue语句并不是跳出当前的循环,它只是终止一次循环,接着进行下一次循环是否执行的判定。continue语句的一般语法格式如下:
continue;
3.3常用的.NET框架类
面向对象语言的一大优势就在于代码的重用。学习面向对象语言,很大的一部分在于学习框架类的使用,熟练使用.NET提供的框架类,将使编程工作事半功倍。3.3.1DateTime类C#语言中的DateTime类提供了一些常用的日期时间方法与属性,该类属于System命名空间,在使用模板创建应用程序时,该命名空间的引用已自动生成,因此可以直接使用DateTime类。DateTime常用的构造函数如表34所示,常用属性如表35所示,常用方法如表36所示。
表34DateTime常用的构造函数
名称主 要 功能
DateTime(int32, int32, int32)将DateTime结构的新实例初始化为指定的年、月和日DateTime(int32, int32, int32,int32, int32, int32)将DateTime结构的新实例初始化为指定的年、月、日、小时、分钟和秒DateTime(int32, int32, int32, int32, int32, int32, int32)将DateTime结构的新实例初始化为指定的年、月、日、小时、分钟、秒和毫秒
表35DateTime的常用属性
名称类型主 要 功 能
DateDateTime获取此实例的日期部分Dayint32获取此实例所表示的日期为该月中的第几天DayOfWeekSystem.DayOfWeek获取此实例所表示的日期是星期几DayOfYearint32获取此实例所表示的日期是该年中的第几天Hourint32获取此实例所表示日期的小时部分Millisecondint32获取此实例所表示日期的毫秒部分Minuteint32获取此实例所表示日期的分钟部分Monthint32获取此实例所表示日期的月份部分NowDateTime获取一个DateTime对象,该对象设置为此计算机上的当前日期和时间,表示为本地时间Secondint32获取此实例所表示日期的秒部分Tickslong获取表示此实例的日期和时间的计时周期数TimeOfDayDateTime获取此实例的当天的时间TodayDateTime获取当前日期UtcNowDateTime获取一个DateTime对象,该对象设置为此计算机上的当前日期和时间,表示为协调通用时间(UTC)Yearint32获取此实例所表示日期的年份部分
表36DateTime的常用方法
名称主 要 功 能
Parse(String)将日期和时间的指定字符串表示形式转换为其等效的DateTimeParse(String, IFormatProvider)
使用指定的区域性特定格式信息,将日期和时间的指定字符串表示形式转换为其等效的DateTimeParse(String, IFormatProvider, DateTimeStyles)使用指定的区域性特定格式信息和格式设置样式将日期和时间的指定字符串表示形式转换为其等效的DateTimeToString()
将当前DateTime对象的值转换为其等效的字符串表示形式(重写ValueType.ToString())ToString(IFormatProvider)
使用指定的区域性特定格式信息将当前DateTime对象的值转换为它的等效字符串表示形式ToString(String)
使用指定的格式将当前DateTime对象的值转换为它的等效字符串表示形式ToString(String, IFormatProvider)
使用指定的格式和区域性特定格式信息将当前DateTime对象的值转换为它的等效字符串表示形式TryParse(String, DateTime)
将日期和时间的指定字符串表示形式转换为其DateTime等效项,并返回一个指示转换是否成功的值TryParse(String, IFormatProvider, DateTimeStyles, DateTime)
使用指定的区域性特定格式信息和格式设置样式,将日期和时间的指定字符串表示形式转换为其DateTime等效项,并返回一个指示转换是否成功的值
例如,想定义一个新的DateTime对象,实例化时想初始为2015年10月1日,语句如下:
DateTime dt = new DateTime(2015,10,1);
如果加上时、分、秒,应该使用下一个构造函数:
DateTime dt = new DateTime(2015,10,1,23,59,59);
这个语句将dt初始化为2015年10月1日23点59分59秒,如果再确切一些的时间,可以使用下一个构造函数,用法和前两个一样。对于以当前日期时间为参照的操作,可以使用该类的Now属性及其方法,如表37所示。
表37日期时间类的Now属性的常用方法与属性
方法与属性主 要 功 能
DateTime.Now.ToLongDateString()获取当前日期字符串DateTime.Now.ToLongTimeString()获取当前时间字符串DateTime.Now.ToShortDateString()获取当前日期字符串DateTime.Now.ToShortTimeString()获取当前时间字符串DateTime.Now.Year获取当前年份DateTime.Now.Month获取当前月份DateTime.Now.Day获取当前日DateTime.Now.Hour获取当前小时DateTime.Now.Minute获取当前分钟DateTime.Now.Second获取当前秒DateTime.Now.DayOfWeek当前为星期几DateTime.Now.AddDays(以天为单位的双精度实数)增减天数后的日期
以当前系统时间为例使用日期时间类,例如:
DateTime.Now.ToLongDateString();// 2016年4月7日
DateTime.Now.ToShortDateString();//2016/4/7
DateTime.Now.ToLongTimeString();//10:15:20
(DateTime.Now.ToShortTimeString();//10:15
DateTime.Now.DayOfWeek;//Tuesday
DateTime.Now.AddDays(1.5); //2016/4/7 22:15:20
【例37】判断当前时间是上午还是下午,在网页中输出问候语句,上午好的字体颜色是红色,下午好的字体颜色是绿色。Page_Load中代码如下:
protected void Page_Load(object sender, EventArgs e)
{
int h;
h = DateTime.Now.Hour;
if (h <= 12)
{
Response.Write(“今天是” DateTime.Now.ToLongDateString() “,上午好!“);
}
else
{
Response.Write(“今天是” DateTime.Now.ToLongDateString() “,” “下午好!“);
}
}
执行上述程序的运行结果如图37所示。
图37例37运行结果
3.3.2Math类C#语言中的Math类提供了一些常用的数学方法与属性,该类属于System命名空间。Math类是一个密封类,有两个公共字段和若干静态数学方法。Math类常用的方法与属性如表38所示。
表38Math类常用方法与属性
方法与属性主 要 功 能
Math.PI得到圆周率Math.E得到自然对数Math.Abs(数值参数)求值方法Math.Cos(弧度值)求余弦值方法Math.Sin(弧度值)求正弦值方法Math.Tan(弧度值)求正切值方法Math.Max(数值1,数值2)求值方法Math.Min(数值1,数值2)求小值方法Math.Pow(底数,指数)求幂方法Math.Round(实数)
Math.Round(实数,小数位)求保留小数值方法
Math.Sqrt(平方数)求平方根方法
3.3.3Random类Random类提供了产生随机数的方法,该方法必须由Random类创建的对象调用。 Random类属于System命名空间,创建对象的格式为:
Random 对象名 = new Random();
Random类的常用方法如表39所示。
表39Random类的常用方法
方法主 要 功 能对象名.Next()产生随机数对象名.Next(正整数)产生0~指定正整数之间的随机数对象名.Next(整数1,整数2)产生两个指定整数之间的随机整数对象名.NextDouble()产生0.0~1.0之间的随机实数
需要说明的是,使用Random对象产生随机数时,下界包含在随机数内,而上界不包含在随机数内。例如:
Random r = new Random();
int n = r.Next(1,10);//产生的随机数包含1,但不包含10。
3.4C#面向对象编程
面向对象技术是一种新的软件技术,其概念来源于程序设计,从20世纪60年代提出面向对象的概念,到现在已发展成为一种比较成熟的编程思想,并且逐步成为目前软件开发领域的主流技术。说明: 本节是为了方便介绍类与对象的概念,所有例题采用.NET平台中的控制台应用程序。控制台应用程序是指Windows下的单机应用程序,采用控制台输出程序结果。创建控制台应用程序的方法如下。(1) 选择“文件”→“新建项目”选项,弹出“新建项目”对话框,如图38所示。
图38“新建项目”对话框
(2) 在该对话框中的左侧栏选中Visual C#语言,在中间栏选择“控制台应用程序”。(3) 在下方选择好项目名称和存储位置。3.4.1类与对象对象(Object)是整个面向对象程序设计的核心。什么是对象?在日常生活中,每天接触的每个具体的事物就是对象。例如,你的同学张某,走到路上看到的一辆白色Jeep越野车,校园里那只流浪的小狗,你的手机等一切具体而非抽象的食物。在计算机中如何来描述这些对象呢?例如,来描述白色Jeep越野车,可以描述这种车的静态特征: 品牌、颜色、价格、车重、油耗、动力等,这些静态特征被称为属性,只描述属性并不能描述一个生动的、漂亮的白色Jeep越野车,还可以描述这辆车的动态特性,如车的启动、刹车、鸣笛等,这样的动态特性被称为行为或方法,当为属性赋予具体数值,定义具体的方法的时候,一个对象就被创造出来了。对象是所有数据及可对这些数据施加的操作结合在一起所构成的独立单位的总称,是拥有具体数据和行为的独立个体。对象(Object)由属性(Attribute)和行为(Action)两部分组成。对象只有在具有属性和行为的情况下才有意义,属性是用来描述对象静态特征的一个数据项,行为是用来描述对象动态特征的一个操作。对象是包含客观事物特征的实体,是属性和行为的封装体。那么在赋值之前的那个状态的事物被称为什么呢?来看这个状态的特点: 它可以描述出某一类型的事物,换言之,这个状态描述的是一个模型,是抽象的、非具体的,它被称为类。类(Class)是对一组客观对象的抽象,是具有共同属性和操作的多个对象的相似特性的统一体。它为属于该类的全部对象提供了统一的抽象描述,其内部包括属性和行为两个主要部分,类是对象集合的再抽象。类与对象的关系如同一个模具与用这个模具铸造出来的铸件之间的关系。类给出了属于该类的全部对象的抽象定义,而对象则是符合这种定义的一个实体。所以,一个对象又称为类的一个实例(Instance)。在C#语言中,使用关键字class来定义一个类,格式如下:
class 类名
{
//类成员
}
【例38】定义一个Person类。
class Person
{
}
【例39】定义一个Point类,它的作用是标明一个二维坐标。
class Point()
{
}
定义类的终目的就是用类来创建对象,对象才是人们编程的核心。当定义好一个类之后,可以用它来定义变量,也可以用它来创建对象(也被称为实例化一个对象),创建对象使用关键字new,一般格式如下:
类名对象名 = new 类名();
或者,将声明和实例化分为两行代码:
类名对象名;
对象名 = new 类名();
注意: 关键字new后面的类名()实际应该是构造函数名,到目前为止,只知道是类名就可以了,因为构造函数与类同名。【例310】为定义的Person类创建两个对象,名为s1和s2。程序代码如下:
class Program
{
static void Main()
{
Person s1=new Person();//声明并实例化一个对象
Person s2;//声明一个变量
s2=new Person();//将声明的变量实例化为一个对象
}
}
public class Person
{
}
当使用new关键字来实例化一个对象的时候,这意味着什么呢?当人们只是声明一个变量的时候,内存中并没有为这个变量分配相应的存储空间,只有当使用new关键字来实例化它时,内存中才为这个对象分配对应大小的存储空间,在每个对象的存储空间中,根据类的定义中所包含的成员,它们都有一份自己独立的数据,根据构造函数为对象中的各实例数据成员赋值,并返回一个对实例的引用,存储空间大小由对象的成员个数及类型来决定。这个阶段称为对象的构造阶段,初始化过程由构造函数完成。在应用程序结束之前的某个时候,对象后一次被调用之后将被删除,这个阶段称为析构阶段,此时常常需要执行一些清理工作,如释放内存,系统的“运行时”会在后一次访问对象之后,自动调用析构函数完成。这个析构过程是.NET系统的垃圾自动回收机制。从构造阶段到析构阶段被称为对象的生命周期。在这个示例中,没有数据或方法与Person类关联,所以相当于实例化了一个完全没用的对象。但一般的情况是当描述一个对象时,需要使用一些数据和动作来表示对象特征,它们被称为类的成员。面向对象程序设计的优点之一就是数据的安全性,安全性通过访问限制修饰符得到了保证,访问限制修饰符规定了类的每个成员的访问级别,它们有以下几种。(1) public: 成员可以由任何代码访问。(2) private: 成员只能由类中的代码访问(默认关键字)。(3) internal: 成员只能被项目内部的代码访问。(4) protected: 成员只能由本类或派生类中的代码访问。internal和protected两个关键字可以合并使用,所以也有protected internal成员,这样的成员只能由本类及项目中派生类的代码来访问。除了这些修饰符,还有上面提过的关键字static,static和这些关键字是可以根据需要并列使用的。原则上,将类的数据(即字段)定义为私有的,只能在类中的代码对其访问,防止类外代码改变重要数据造成错误; 一些成员(如方法)定义为公有的,能保证类外的代码对类正常访问和使用; 一些成员定义为受保护的,使得派生类能够访问,其他类不能访问。3.4.2类的成员1. 字段
在C#语言中,字段(field)的定义、作用及使用方法类似于面向过程语言(如C语言)里面的变量,定义的时候也需要指定存储的数据类型,除此之外,由于它是类的成员,还需要指定访问级别,因此字段定义格式如下:
访问限制修饰符 数据类型 字段名;
在使用类的成员时,如果在类的内部,直接使用字段的名字; 如果是在类的外部,要通过对象来使用,格式为“对象名.成员名”。可以和变量一样用“=”为字段赋值,也可以读取字段的值。【例311】为Person类添加年龄、姓名字段,为s1对象年龄字段赋值21,为s2对象年龄字段赋值22,并输出。程序代码如下:
class Person
{
public int age;
public string name;
}
//在Program中为字段赋值并读取字段的值
class Program
{
static void Main()
{
Person s1=new Person();
Person s2;
s2=new Person();
s1.name=”John”;//为s1的name字段赋值为John
s1.age=21;//为s1的age字段赋值为21
s2.name=”Tom”; //为s2的name字段赋值为Tom
s2.age=22;//为s2的age字段赋值为22
Console.WriteLine(“{0}的年龄为{1},{2}的年龄为{3}.”,s1.name,s1.age,s2.name,s2.age);
}
}
执行上述程序的运行结果如图39所示。
图39程序运行结果
在例311中,代码中的Person类增加了两个成员——age和name,类型分别是整型和字符串型,访问控制为public。这意味着: 首先,在用new实例化类的一个对象时,每个对象的存储空间中都有这两个成员存在,而且可以计算出每个实例化的对象在内存中所占空间大小,它们等于这两个字段所占空间大小(这里比较特殊的是string类型,string类型是一个没有上限的变量类型),对象p在内存中所占大小为16字节(两个double变量的大小); 同时,在类的外部的代码中,只要实例化了该类的一个对象,就能访问这个对象的公共字段,可以修改它们的值(如语句s1.age=21;),也可以读取它们的值(如语句Console.WriteLine(“{0}的年龄为{1},{2}的年龄为{3}.”,s1.name,s1.age,s2.name,s2.age);)。2. 方法方法又称为函数(Function),是一种组合一系列语句以执行一个特定操作或计算一个特殊结果的方式。方法的定义格式如下:
访问限制修饰符 返回值类型 方法名(参数类型参数1, 参数类型参数2,…,参数类型参数n)
{
//方法体
return 返回值;
}
其中,访问限制修饰符返回值类型方法名(参数类型参数1,参数类型参数2,…,参数类型参数n)(包括参数的顺序)被称为方法的签名。访问修饰符规定了方法被访问的级别; 返回值类型表明调用并执行此方法后是否得到一个值,得到的值是什么类型; 参数是调用者与方法之间交换数据的途径。可以看出,方法的签名标识了某个类中的一个方法,在一个类中,不允许有相同签名的两个方法。下面先通过一个简单的示例初步认识方法的定义。【例312】为Person类添加一个输出个人信息的方法。程序代码如下:
class Person
{
public int age;
public string name;
public void PrintInfo()//此方法用来输出对象的信息
{
Console.WriteLine(“My name is {0},I’m {1}”,name,age);
}
}
//在Program中使用这个方法
class Program
{
static void Main()
{
Person s1=new Person();
Person s2;
s2=new Person();
s1.name=”John”;
s1.age=21;
s2.name=”Tom”;
s2.age=22;
s1.PrintInfo();//调用PrintInfo()函数
s2.PrintInfo();
}
}
执行上述程序的运行结果如310所示。
图310程序运行结果
在Main()函数中通过对象s1和s2调用了PrintInfo()函数,Main()函数被称为调用者。由于方法总是和类联系一起,“调用一个方法”概念上等价于“向一个类发送一条消息”。上面的示例中,由于PrintInfo方法只是简单地输出对象的个人信息,方法既没有参数,也没有返回值(返回值类型标为void)。3. 构造函数构造函数(Constructor)是一种特殊的成员函数,它主要用于为对象分配空间,完成初始化的工作。它为程序提供一种方式,在创建对象的同时指定所需的数据。构造函数有以下几个特点。(1) 构造函数的名称必须与类名相同。(2) 构造函数可以带参数,但没有返回值。(3) 构造函数只能在对象定义时,由new关键字自动调用,不能显示调用。(4) 如果没有给类定义构造函数,编译系统会自动生成一个默认的构造函数,其形式如下:
public 类名():base(){ }
(5) 构造函数可以重载,但不能继承。【例313】为Person类添加一个构造函数,在此构造函数中为姓名和年龄提供初始值。程序代码如下:
class Person
{
private int age;
private string name;
public Person(int inAge, string inName)//有参构造函数
{
name=inName;
age=inAge;
}
public void PrintInfo()
{
Console.WriteLine(“My name is {0},I’m {1}”,name,age);
}
public void SetInfo(int inAge, string inName)//通过参数设置个人信息的方法
{
name=inName;
age=inAge;
}
}
//在Program中使用这个有参构造方法为s1和s2对象初始化
class Program
{
static void Main()
{
Person s1=new Person(21,”Tom”);
Person s2=new Person(22,”John”);
s1.PrintInfo();
s2.PrintInfo();
}
}
执行上述程序的运行结果如图311所示:
图311程序运行结果
在上面的代码中,可以看出在Person类中添加了一个有参构造函数,因此执行了“Person s1=new Person(21,”Tom”);”语句时调用这个构造函数为字段name和age初始化。值得注意的是,因为要在类之外的代码中创建类的对象,所以构造函数的访问限制修饰符一般情况下都为public。现在,请思考一个问题,在前面的代码中并没有构造函数出现,为什么能使用new来实例化一个对象呢?这是因为当没有在代码中显式地定义任何构造函数,C#编译器在编译时会自动添加一个如下形式的构造函数:
public Person():base()
{
}
这个构造函数不获取参数,所以它被称为默认构造函数(Default Constructor)。必须注意的是,一旦为一个类显式添加了一个构造函数,C#编译器不再提供默认构造函数,即一旦添加了一个有参的构造函数,在Main()中实例化一个Person时,就必须指定名字和年龄,如果再像以前那样使用语句“Person s1=new Person();”来实例化一个Person时,代码在编译的时候会产生错误。因为定义了public Person(int inAge, string inName)之后,编译器不再添加默认构造函数Person()。如果此时仍想使用语句“Person s1=new Person();”来实例化一个Person时,需要手动添加这样的一个构造函数。【例314】为Person类添加一个有参构造函数(在此构造函数中为姓名和年龄提供初始值)和一个无参构造函数。程序代码如下。
class Person
{
private int age;
private string name;
public Person(int inAge, string inName)//有参构造函数
{
name=inName;
age=inAge;
}
public Person() //无参构造函数
{
}
public void PrintInfo()
{
Console.WriteLine(“My name is {0},I’m {1}”,name,age);
}
public void SetInfo(int inAge, string inName)//通过参数设置个人信息的方法
{
name=inName;
age=inAge;
}
}
//在Program中使用这个有参构造方法为s1对象初始化
class Program
{
static void Main()
{
Person s1=new Person(21,”Tom”);
Person s2=new Person();
s2.SetInfo(22,”John”);
s1.PrintInfo();
s2.PrintInfo();
}
}
执行上述程序的运行结果如图312所示。
图312程序运行结果
可以看出来,语句“Person s1=new Person(21,”Tom”);”与“Person s1=new Person(); s1.SetInfo(21,”Tom”);”(或者“s1.age=21;s1.name=”Tome”;”)对字段初始化的效果是一样的,只是初始化的时机不同。这样一来,Person类就有了两个构造函数,同样地,这两个构造函数名称相同,参数不同,称为构造函数的重载。4. 属性类还有一种十分重要的成员是属性。属性本质上和字段作用类似,也是用来读写类中的数据的,读写的方式和字段一样。同时,由于属性拥有两个类似函数的块(一个用于获取属性的值,一个用于设置属性的值),在读写数据之前,属性还可以执行一些额外的操作,如判断读写行为是否合法,终决定是否执行数据的读写操作。因此,属性对数据具有更好的保护性。再来说说这两个块。这两个块也称为访问器,分别用get和set关键字来定义,可以用来控制对属性的访问级别。可以忽略其中的一个块来创建只读或只写属性(忽略get块创建只写属性,忽略set为只读属性)。属性的定义方式如下。
访问限制修饰符返回值类型属性名
{
get
{
//…
}
set
{
//…
}
}
【例315】为Point类添加属性成员。程序代码如下:
class Point
{
private double x,y;
public Point(double a,double b)
{
x = a;
y = b;
}
public double XProp
{
get
{
return x;
}
set
{
x = value;
}
}
public double YProp
{
get
{
return y;
}
set
{
y = value;
}
}
public void Display()
{
Console.WriteLine(“横坐标是{0},纵坐标是{1}”,x,y);
}
}
class Program
{
static void Main()
{
Point p = new Point(5,10);
p.Display();
p.XProp = -5;//直接为属性赋值
p.YProp = -10;
p.Display();
Console.WriteLine(“属性XProp的值为{0},属性YProp的值为{1}”,p.XProp, p.YProp); //直接像字段一样读取属性的值
}
}
执行上述程序的运行结果如图313所示。
图313程序运行结果
属性不仅能控制赋值范围,而且能控制数据是否可读写,还可以控制读写的访问范围。如果只有set块,就意味着只能给该属性赋值,该属性被称为只写属性; 如果只有get块,就意味着该属性只能读取,不能修改值,被称为只读属性。只读属性:
public int AgeProp
{
get
{
return age;
}
}
又如:
public int Age
{
get
{
return birthDate.Year-DateTime.now.Year 1;
}
}
只写属性:
public int AgeProp
{
set
{
if( value > 0 && value <= 100)
age = value;
}
}
3.4.3继承如果所有的类都从头写起,那么现在应用程序肯定没有这么丰富。面向对象技术的优点之一是可以继承,继承使得设计者能对现有的类型进行扩展,以便添加更多的功能。前面已经定义了一个Person类,如果设计者想再定义一个Student类,那么就可以在Person类的基础上进行扩展。可以分析一下,Student类除了有Person类的那些特性以外,还需要哪些自己的特性呢?因此可以再为Student类添加Phone、Email、Score等属性。此时,称Person类为父类(基类),Student类为子类(派生类)。子类拥有父类的可继承成员。定义派生类格式如下:
class 子类名: 父类名
{
//…
}
为了清楚地说明继承,简化Person类,以便代码看起来比较清晰。【例316】定义一个Student类,从Person类中继承。程序代码如下:
class Person
{
public string Name{ get; set;}
public DateTime BirthDate{ get;set; }
}
class Student : Person
{
public string Phone{ get; set; }
public string Email{ get; set; }
public int Score{ get; set; }//高考成绩
}
class Program
{
static void Main()
{
Student s = new Student();
s.Name = “Tom”;
s.BirthDate = DateTime.Parse(“1990-1-1”);
s.Email = “[email protected]”;
//…
}
}
通过继承,虽然Student类没有直接定义Name属性,但Student的所有实例仍然可以访问来自Student类的Name属性,并把它作为Student的一部分来使用。这是因为在内存中,Student的对象是由父类中的成员和自己类中新增加的成员组成的。在例316中,基类中的所有成员都可由派生类使用,那是因为将基类所有成员都定义为public,如果访问修饰符是private,派生类则不能访问该成员。除了public或private之外,还可以对成员进行更细致的封装。可以用protected定义只有派生类才能访问的成员。【例317】为Person类定义3种不同访问级别的成员,在派生类Student中以及在其他类中利用派生类的对象对基类成员进行访问,实现3种成员的访问限制。程序代码如下:
class Person
{
private string name;
protected DateTime birthDate;
pulbic string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
class Student : Person
{
public string Phone{ get; set; }
public string Email{ get; set; }
public int Score{ get; set; }//高考成绩
public Student()
{
name = “noname”; //错误!
}
public int Age
{
get
{
return DateTime.Now.Year- birthDate.Year 1;
}
}
public DateTime BirthDate
{
get
{
return birthDate;
}
set
{
birthDate = value;
}
}
}
class Program
{
static void Main()
{
Student s = new Student();
s.name = “Tom”;// 错误!name字段是私有(private)的!
s.Name = “Tom”; //正确!Name属性是公有(pulic)的!
s.birthDate = DateTime.Parse(“1990-1-1”);//错误!birthDate字段是protected,只有在本类和派生类内部能够被访问
s.BirthDate = DateTime.Parse(“1990-1-1”); //正确!
s.Email = “[email protected]”;
//…
}
}
在例317的代码中,斜体字是错误的代码。以上代码说明: name字段作为父类的私有成员,不能在本类以外的代码中访问; birthDate是父类中protected类型的成员,可以在派生类中被访问(属性BirthDate与父类的受保护字段birthDate关联),但在本类和派生类的外部被访问就会产生错误; public成员在任何代码中都可以被访问。本章小结
本章简要介绍了C#的部分语法知识,包括数据、流程控件、类的定义和使用等。由于本书的重点在于ASP.NET网站设计,因此关于C#语言中的更多语法细节没有在此介绍,只对涉及接下来的学习ASP.NET的知识必要的语法基础做了说明。如果读者对C#语言有更多的兴趣,可以参考其他经典书籍。习题
一、 单选题1. C#每个语句行以()结束。
A. #B. 句号C. 逗号D. 分号2. 数组的下标是从()开始。A. 1B. -1C. 0D. 23. 数组对象是通过()运算符在运行时动态产生的。A. newB. intC. floatD. oid4. C#是一种安全的、稳定的、简单的,由()衍生出来的面向对象的编程语言。A. MASMB. Visual BasicC. JavaD. C和C 5. 对象是()的实例化。A. 类B. 事件C. 方法D. 属性6. 执行如下语句后,sum的值为()。
int[ ] a = new int[6];
int sum=0;
for(int i=0; i<=5; i )
{ a[i]=i;
sum =a[i];}
A. 0B. 5C. 15D. 207. 执行“a=5 % 3”语句后,a的值为()。A. 0B. 2C. 3D. 58. 下面的()语句可以取回当前的年份。A. DateTime.NowB. DateTime.Now.YearC. DateTime.Now.HourD. DateTime.Now.Month二、 填空题1. C#语言有15种不同的数据类型,这15种数据类型分为两大类: 和。2. C#语言中,类中具有字段的使用形式,又有方法的本质的成员是。3. 为了用1到10之间的随机整数给整型变量i赋值,应该使用语句Random ran=new Random(); int i =。三、 操作题1. 用ASP.NET创建网页,在页面上用“*”输出空心菱形。2. 用C#语言创建一个控制台应用程序,编写矩形类Rectangle,类中包含长和宽字段,包含求面积和周长的只读属性,长和宽只写属性; 包含两个构造函数: 无参构造函数和有参构造函数; 有参构造函数中初始化长和宽字段。
评论
还没有评论。