资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C#,实用教程,第,5,章,Windows,应用程序,第,4,章 面向对象编程进阶,第,3,章 面向对象编程基础,第,2,章,C#,编程基础,第,1,章,C#,快速入门,1,C#,实用教程,第,10,章,Web,应用程序,第,9,章,C#,多线程技术,第,8,章 数据库应用,第,7,章 文件操作,第,6,章,GDI+,编程,2,1.1 C#,的优势,作为编程语言,,C#,是现代的、简单的、完全面向对象的,而且是类型安全的。重要的是,,C#,是一种现代编程语言。在类、名字空间、方法重载和异常处理等方面,,C#,去掉了,C+,中的许多复杂性,借鉴和修改了,Java,的许多特性,使其更加易于使用,不易出错。,下面列举了一些,C#,在设计上的优点:,3,1.1 C#,的优势,面向对象,现代性,类型安全性,版本处理技术,C#,在设计上的优点,简单性,4,简单性,1.,没有指针是,C#,的一个显著特性,用户使用一种可操控的(,Managed,)代码进行工作时,直接的内存存取,将是不允许的。,2.,在,C#,中不再需要记住那些源于不同处理器结构的数据类型,现代性,1.,用户可以使用一个新的,decimal,数据类型进行货币计算。,2.C#,通过代码访问安全机制来保证安全性,根据代码的身份来源,可以分为不同的安全级别,不同级别的代码在被调用时会受到不同的限制。,面向 对象,1.C#,支持面向对象的所有关键概念:封装、继承和多态性。,2.C#,的继承机制只允许一个基类。如果需要多重继承,用户可以使用接口。,5,类型安全性,1.C#,实施了最严格的类型安全机制来保护它自身及其垃圾收集器。,2.,边界检查。,3.,算术运算溢出检查。,4.C#,中传递的引用参数是类型安全的。,版本处,理技术,C#,尽其所能支持,DLL,版本处理功能,虽然,C#,自己并不能保证提供正确的版本处理结果,但它为程序员提供了这种版本处理的可能性。有了这个适当的支持,开发者可以确保当他开发的类库升级时,会与已有的客户应用保持二进制级别上的兼容性。,6,1.2,第一个,C#,程序,首先看,控制台应用程序,的版本。,【,例,1.1】,在控制台窗口中输出,“,Hello World!”,字样。,在,Visual C#.NET,开发环境中新建一个控制台应用程序项目,,并在源代码文件中输入如下语句:,using System;,class HelloWorld,public static void Main(),Console.WriteLine(Hello World!);,程序运行结果下图所示。,Hello World,!,7,将此内容保存到文件,EX1_1.cs,中,然后选择菜单“调试,”“启动”或直接按,F5,键运行此程序。,也可以不使用,Visual C#.NET,环境,直接用文本编辑工具输入以上代码,并且保存到,Helloworld.cs,文件中,再通过开始菜单的“程序”“,Microsoft Visual Studio 2005,”“,Visual Studio Tools”“Visual Studio 2005,命令提示”打开命令行窗口,在命令窗口中输入:,csc /target:exe EX1_1.cs,程序运行结果如图,1.1,所示。,Hello World,!,8,下面再看,Windows,应用程序,的版本。,【,例,1.2】,弹出一个消息对话框显示“,Hello World!”,字样。,用“,Windows,应用程序,”模板建立项目,或者使用文本编辑工具输入源代码如下:,using System;,using System.Windows.Forms;,class HelloWorld,public static void Main(),MessageBox.Show(Hello World,Message from C#);,9,这次需要增加对,System.Windows.Forms,命名空间的引用,选择菜单“项目”“添加引用,”,打开“添加引用”对话框,在列表中找到并选中“,System.Windows.Forms.dll”,,然后单击“选择”按钮,最后单击“确定”按钮完成添加。将文件另存为,EX1_2.cs,,在开发环境中按,F5,键编译运行程序,如果用命令行方式编译请参照控制台版,编译命令如下:,csc/target:winexe EX1_2.cs,程序的运行结果如图,1.2,所示。,10,通过上述两段代码来认识,C#,:,1,代码最前面是以,using,关键字开始的命名空间导入语句,然后是使用,class,关键字对类,HelloWorld,的定义。,2,命名空间是为了防止相同名字的不同标识符发生冲突而设计的隔离机制。,3,在,.NET,框架类库中提供的不同组件都被包含在一定的命名空间中,所以要使用这些组件也必须通过,using,关键字开放相应的命名空间,使得相应的标识符对编译器可见,如果没有使用,using,关键字,那么相应的标识符就应包含完整的空间路径,。,4,由于,C#,是一种完全的面向对象的语言,所以不会有独立于类的代码出现,应用程序的入口也必须是类的方法,,C#,规定命名为,Main,的方法作为程序的入口,5,C#,是一种大小写敏感的语言!,11,第,2,章,C#,编程基础,C#,的基本数据类型、变量、常量、表达式、程序流程控制语句及数组等概念是,C#,程序设计的基础,掌握这些基本知识是编写正确程序的前提。,2.1,基本类型,C#,的基本数据类型、变量、常量、表达式、程序流程控制语句及数组等概念是,C#,程序设计的基础,掌握这些基本知识是编写正确程序的前提。,12,第,2,章,C#,编程基础,C#,的基本数据类型、变量、常量、表达式、程序流程控制语句及数组等概念是,C#,程序设计的基础,掌握这些基本知识是编写正确程序的前提。,13,2.2.1,值类型,所谓,值类型,就是一个包含实际数据的量。当定义一个值类型的变量时,,C#,会根据它所声明的类型,以,堆栈,方式分配一块大小相适应的存储区域给这个变量,随后对这个变量的读,/,写操作就直接在这块内存区域进行。,.,例如:,int iNum=10,;/,分配一个,32,位内存区域给变量,iNum,,并将,10,放入该内存区域,iNum=iNum+10;,/,从变量,iNum,中取出值,加上,10,,再将计算结果赋给,iNum,图,2.1,值类型操作示意图,14,表,2.1 C#,简单类型,C#,关键字,.NET CTS,类型名,说 明,范围和精度,bool,System.Boolean,逻辑值(真或假),true,false,sbyte,System.SByte,8,位有符号整数类型,128127,byte,System.Byte,8,位无符号整数类型,0255,short,System.Int16,16,位有符号整数类型,3276832767,ushort,System.UInt16,16,位无符号整数类型,065535,int,System.Int32,32,位有符号整数类型,21474836482147483647,C#,中的值类型包括:简单类型、枚举类型和结构类型。,15,续表,C#,关键字,.NET CTS,类型名,说 明,范围和精度,uint,System.Uint32,32,位无符号整数类型,04294967295,long,System.Int64,64,位有符号整数类型,92233720368547758089223372036854775807,ulong,System.UInt64,64,位无符号整数类型,018446744073709551615,char,System.Char,16,位字符类型,所有的,Unicode,编码字符,float,System.Single,32,位单精度浮点类型,(大约,7,个有效十进制数位),double,System.Double,64,位双精度浮点类型,(大约,1516,个有效十进制数位),decimal,System.Decimal,128,位高精度十进制数类型,(大约,2829,个有效十进制数位),表中“,C#,关键字”是指在,C#,中声明变量时可使用的类型说明符。,16,2.1.2,引用类型,引用类型,包括,class,(类)、,interface,(接口)、数组、,delegate,(委托)、,object,和,string,。其中,object,和,string,是两个比较特殊的类型。,object,是,C#,中所有类型(包括所有的值类型和引用类型)的根类。,string,类型是一个从,object,类直接继承的密封类型(不能再被继承),其实例表示,Unicode,字符串。,一个引用类型的变量不存储它们所代表的实际数据,而是存储实际数据的引用。,引用类型分,两步,创建:首先在堆栈上创建一个引用变量,然后在堆上创建对象本身,再把这个内存的句柄(也是内存的首地址)赋给引用变量。,17,例如:,string s1,s2;,s1=ABCD;s2=s1;,其中,,s1,、,s2,是指向字符串的引用变量,,s1,的值是字符串,ABCD,存放在内存的地址,这就是对字符串的引用,两个引用型变量之间的赋值,使得,s2,、,s1,都是对,ABCD,的引用,如图,2.2,所示。,图,2.2,引用类型赋值示意,18,引用类型的值是引用类型实例的引用,特殊值,null,适用于所有引用类型,它表明没有任何引用的对象。当然也可能有若干引用类型的变量同时引用一个对象的实例,对任何一个引用变量作出修改都会导致该对象的值的修改。,注意:,堆栈,是按先进后出(,FILO,)的原则存储数据项的一种数据结构;,堆(,heap,),则是用于动态内存分配的一块内存区域,可以按任意顺序和大小进行分配和释放。,C#,中,值类型就分配在堆栈中,堆栈内存区域内保存着值类型的值,内存区域可以通过变量名来存取。引用类型分配在堆中,对象分配在堆时,返回的是地址,这个地址被赋值给引用。,19,可以把值类型与引用类型的值赋给,object,类型变量,,C#,用“,装箱,”和“,拆箱,”来实现值类型与引用类型之间的,转换,。,“装箱”就是将值类型包装成引用类型的处理过程。当一个值类型被要求转换成一个,object,对象时,“装箱”操作自动进行,它首先创建一个对象实例,然后把值类型的值复制到这个对象实例,最后由,object,对象引用这个对象实例。,2.1.3,值类型与引用类型的关系,20,例如,:,using System;,class Demo,public static void Main(),int x=123;,object obj1=x;,/,装箱操作,x=x+100,;/,改变,x,的值,此时,obj1,的值并不会随之改变,Console.WriteLine(x=0,x,);/x=223,Console.WriteLine(obj1=0,obj1);,/obj1=123,该实例的“装箱”操作说明如图,2.3,所示。,21,该实例的“装箱”操作说明如图,2.3,所示。,22,“,拆箱,”操作与“装箱”相反,它是将一个,object,类型转换成值类型。首先检查由,object,引用的对象实例值类型的包装值,然后把实例中的值复制到值类型的变量中。,注意:,当一个“装箱”操作把值类型转换为一个引用类型时,不需要显式地强制类型转换;,而拆箱操作把引用类型转换到值类型时,由于它可以强制转换到任何可以相容的值类型,所以必须显式地强制类型转换。,using System;,class Demo,public static void Main(),int x=123,y;,object obj1=x;/,装箱操作,x=x+100;/,改变,x,的值,此时,obj1,的值并不会随之改变,y=(int)obj1;,/,拆箱操作,必须进行强制类型转换,Console.WriteLine(x=0,x);/x=223,Console.WriteLine(obj1=0,obj1);,/obj1=123,23,2.2,变量与常量,C#,的基本数据类型、变量、常量、表达式、程序流程控制语句及数组等概念是,C#,程序设计的基础,掌握这些基本知识是编写正确程序的前提。,2.2.1,常量,常量,顾名思义就是在程序运行期间其值不会改变的量,它通常可以分为字面常量和符号常量。常量及其使用非常直观,以能读懂的固定格式表示固定的数值,每一种值类型都有自己的常量表示形式。,24,对于一个整数值,默认的类型就是能保存它的最小整数类型,其类型可以分为,int,、,uint,、,long,或,ulong,。如果默认类型不是想要的类型,可以在常量后面加后缀(,U,或,L,)来明确指定其类型。,在常量后面加,L,或,l,(不区分大小写)表示长整型。例如:,32 /,这是一个,int,类型,32L /,这是一个,long,类型,在常量后面加,U,或,u,(不区分大小写)表示无符号整数。例如:,128U /,这是一个,uint,类型,128UL /,这是一个,ulong,类型,整型常量既可以采用十进制也可以采用十六进制,不加特别说明默认为十进制,在数值前面加,0 x,(或,0X,)则表示十六进制数,十六进制基数用,09,、,AF,(或,af,),例如:,0 x20 /,十六进制数,20,,相当于十进制数,32,0 x1F /,十六进制数,1F,,相当于十进制数,31,1,整数常量,25,一般带小数点的数或用科学计数法表示的数都被认为是,浮点数,,它的数据类型默认为,double,类型,但也可以加后缀符表明三种不同的浮点格式数,定点数,(,Fixed Point Number,)。在这种表达方式中,小数点固定的位于实数所有数字中间的某个位置,.,在数字后面加,F,(,f,),表示是,float,类型。,在数字后面加,D,(,d,),表示是,double,类型。,在数字后面加,M,(,m,),表示是,decimal,类型。,例如:,3.14,3.14e2,0.168E,2 /,这些都是,double,类型常量,其中,3.14e2,相当于,/0.618E,2,相当于,3.14F,0.168f /,这些都是,float,类型常量,3.14D,0.168d /,这些都是,double,类型常量,3.14M,0.168m /,这些都是,decimal,类型常量,2,浮点常量,26,字符常量,,简单地说,,就是用单引号括起来的单个字符,,如,A,,它占,16,位,以无符号整型数的形式存储这个字符所对应的,Unicode,代码。这对于大多数图形字符是可行的,但对一些非图形的控制字符(如回车符)则行不通,所以字符常量的表达有若干种形式。,单引号括起的一个字符,如,A,。,十六进制的换码系列,以“,x”,或“,X”,开始,后面跟,4,位十六进制数,如,X0041,。,Unicode,码表示形式,以“,U”,或“,u”,开始,后面跟,4,位十六进制数,如,U0041,。,显式转换整数字符代码,如(,char,),65,。,字符转义系列,如表,2.2,所示。,3,字符常量,27,转 义 字 符,含 义,Unicode,码,转 义 字 符,含 义,Unicode,码,单引号,u0027,b,退格符,u0008,双引号,u0022,f,走纸换页符,u000C,反斜线字符,u005C,n,换行符,u000A,0,空字符,u0000,r,回车符,u000D,a,警铃符,u0007,t,水平制表符,u0009,v,垂直制表符,u000B,表,2.2,字符转义符,28,字符串常量是用双引号括起的零个或多个字符序列。,C#,支持两种形式的字符串常量,一种是常规字符串,另一种是逐字字符串。,(,1,)常规字符串。双引号括起的一串字符,可以包括转义字符。,例如:,Hello,Worldn,C:windowsMicrosoft /,表示字符串,C:windowsMicrosoft,(,2,)逐字字符串。在常规的字符串前面加一个,,就形成了逐字字符串,,它的意思是字符串中的每个字符均表示本意,不使用转义字符,。如果在字符串中需用到双引号,则可连写两个双引号来表示一个双引号。,例如:,C:windowsMicrosoft,/,与,C:windowsMicrosoft,含义相同,He saidHello to me /,与,He saidHello to me,含义相同,4,字符串常量,29,5,布尔常量,它只有两个值:,true,和,false,。,6,符号常量,在声明语句中,可以声明一个标识符常量,但必须在,定义标识符时就进行初始化,,并且定义之后就不能再改变该常量的值。,具体的格式为:,const,类型 标识符,=,初值,例如:,const double PI=3.14159,30,变量是在程序运行过程中其值可以改变的量,它是一个,已命名的存储单元,,通常用来记录运算的中间结果或保存数据。在,C#,中,每个变量都具有一个类型,它确定哪些值可以存储在该变量中。创建一个变量就是创建这个类型的实例,变量的特性由类型来决定。,C#,中的变量必须先声明后使用。,声明变量包括变量的名称、数据类型,必要时指定变量的初始值。,声明变量的形式:,类型 标识符表,;,或,类型 标识符,=,初值,;,2.2.2,变量,31,标识符必须以字母或者,_,(下划线)开头,后面跟字母、数字和下划线的组合。例如,,name,、,_Int,、,Name,、,x_1,等都是合法的标识符,但,C#,是大小写敏感的语言,,name,、,Name,分别代表不同的标识符,在定义和使用时要特别注意。另外变量名不能与,C#,中的关键字相同,除非标识符是以,作为前缀的。,例如:,int x;/,合法,float y1=0.0,y2=1.0,y3;/,合法,变量说明的同时可以设置初始数值,string char /,不合法,因为,char,是关键字,string char,/,合法,C#,允许在任何模块(,语法块,)内部声明变量,模块开始于“,”,,结束于“,”,。每次进入声明变量所在的模块时,则创建变量并分配存储空间,离开这个模块时,则销毁这个变量并收回分配的存储空间。实际上,变量只在这个模块内有效,所以称为局部变量,这个模块区域就是变量的作用域。,32,表达式是由,操作数和运算符,构成的。操作数可以是常量、变量、属性等;运算符指示对操作数进行什么样的运算。因此,也可以说表达式就是利用运算符来执行某些计算并且产生计算结果的语句。,C#,提供大量的运算符,按需要,操作数的数目,来分,有一元运算符(如,+,)、二元运算符(如,+,,*)、三元运算符(如,?:,)。按运算功能来分,基本的运算符可以分为以下几类:,(,1,)算术运算符,(,2,)关系运算符,(,3,)逻辑运算符,(,4,)位运算符,(,5,)赋值运算符,(,6,)条件运算符,(,7,)其他(分量运算符,,下标运算符,等),2.3,运算符与表达式,33,2.3.1,算术运算符,运算 符,含 义,示例(假设,x,,,y,是某一数值类型的变量),运 算 符,含 义,示例(假设,x,,,y,是某一数值类型的变量),+,加,x+y;x+3;,%,取模,x%y;11%3;11.0%3;,减,x,y;y,1;,+,递增,+x;x+;,*,乘,x*y;3*4;,递减,x;,x,;,/,除,x/y;5/2;5.0/2.0;,算术运算符作用的操作数类型可以是整型也可以是浮点型,运算符如表,2.3,所示,34,其中:,“,+,*/”,运算与一般代数意义及其他语言相同,但需要注意:当“,/”,作用的两个操作数都是整型数据类型时,,其计算结果也是整型。,例如:,4/2 /,结果等于,2,5/2 /,结果等于,2,5/2.0 /,结果等于,2.5,“%”,取模运算,,即获得整数除法运算的余数,所以也称取余。,例如:,11%3/,结果等于,2,12%3 /,结果等于,0,11.0%3 /,结果等于,2,,这与,C/C+,不同,它也可作用于浮点类型的,35,操作数,“,+,”,和,“,”,递增和递减运算符是一元运算符,它作用的操作数必须是变量,不能是常量或表达式。它既可出现在操作数之前(前缀运算),也可出现在操作数之后(后缀运算),前缀和后缀有共同之处,也有很大区别。,例如:,+x,先将,x,加一个单位,然后再将计算结果作为表达式的值。,x+,先将,x,的值作为表达式的值,然后再将,x,加一个单位。,不管是前缀还是后缀,它们操作的结果对操作数而言,都是一样的,操作数都加了一个单位,但它们出现在表达式运算中是有区别的。,例如:,int x,y;,x=5;y=+x;/x,和,y,的值都等于,6,x=5;y=x+;/x,的值是,6,,,y,的值是,5,36,操作数,“,+”,和“,”递增和递减运算符是一元运算符,它作用的操作数必须是变量,不能是常量或表达式。它既可出现在操作数之前(前缀运算),也可出现在操作数之后(后缀运算),前缀和后缀有共同之处,也有很大区别。,例如:,+x,先将,x,加一个单位,然后再将计算结果作为表达式的值。,x+,先将,x,的值作为表达式的值,然后再将,x,加一个单位。,不管是前缀还是后缀,它们操作的结果对操作数而言,都是一样的,操作数都加了一个单位,但它们出现在表达式运算中是有区别的。,例如:,int x,y;,x=5;y=+x;/x,和,y,的值都等于,6,x=5;y=x+;/x,的值是,6,,,y,的值是,5,37,2.3.2,关系运算符,运 算 符,操 作,结果(假设,x,,,y,是某相应类型的操作数),xy,如果,x,大于,y,,则为,true,,否则为,false,=,x=y,如果,x,大于等于,y,,则为,true,,否则为,false,xy,如果,x,小于,y,,则为,true,,否则为,false,=,x,、,=,、,、,flase,在,C#,中是没有意义的。,39,在,C#,中,简单类型和引用类型都可以通过,=,或,!=,来比较它们的数据内容是否相等。对简单类型,比较的是它们的数据值;而对引用类型来说,由于它的内容是对象实例的引用,所以若相等,则说明这两个引用指向同一个对象实例,如果要测试两个引用对象所代表的内容是否相等,则通常会使用对象本身所提供的方法,如,Equals(),。,如果操作数是,string,类型的,则在下列两种情况下被视为两个,string,值相等。,(,1,)两个值均为,null,。,(,2,)两个值都是对字符串实例的非空引用,这两个字符串不仅长度相同,并且每一个对应的字符位置上的字符也相同。关系比较运算“,、,=,、,、,flase,在,C#,中是没有意义的。,40,2.3.3,逻辑运算符,运 算 符,含 义,运 算 符,含 义,&,逻辑与,&,短路与,|,逻辑或,|,短路或,逻辑异或,!,逻辑非,p,q,p&q,p|q,p q,!p,true,true,true,true,false,false,true,false,false,true,true,false,false,true,false,true,true,true,false,flase,flase,false,false,true,假设,p,、,q,是两个布尔类型的操作数,表,2.6,给出了逻辑运算的真值表。,逻辑运算符是用来对两个布尔类型的操作数进行逻辑运算的,运算的结果也是布尔类型,如表,2.5,所示。,41,运算符“,&”,和“,|”,的操作结果与“,&”,和“,|”,一样,但它们的,短路特征,(short cut),使代码的效率更高。所谓短路就是在逻辑运算的过程中,如果计算第一个操作数时,就能得知运算结果就不会再计算第二个操作数,如图,2.4,所示。,42,位运算符主要分为逻辑运算和移位运算,它的运算操作直接作用于操作数的每一位,所以操作数的类型必须是整数类型,不能是布尔类型、,float,或,double,等类型。,如表,2.7,所示。借助这些位运算符可以完成对整型数的某一位测试、设置,以及对一个数的位移动等操作,这对许多系统级程序设计非常重要。,2.3.4,位运算符,运 算 符,含 义,&,按位与,|,按位或,按位异或,按位取反,右移,左移,43,按位异或运算有一个特别的属性,假设有两个整型数,x,和,y,,则表达式,(x y)y,值还原为,x,,利用这个属性可以创建简单的加密程序。例如,using System;,class Encode,public static void Main(),char ch1=O,ch2=K;,int key=0 x1f;,Console.WriteLine(,明文:,+ch1+ch2);,ch1=(char)(ch1 key);,ch2=(char)(ch2 key);,Console.WriteLine(,密文:,+ch1+ch2);,ch1=(char)(ch1 key);,ch2=(char)(ch2 key);,Console.WriteLine(,解码:,+ch1+ch2);,44,移位运算符有两个:,一个左移(,),。,语法形式:,value num_bits,左操作数,value,是要被移位的值,右操作数,num_bits,是要移位的位数。,(,1,)左移。将给定的,value,向左移动,num_bits,位,左边移出的位丢掉,右边空出的位填,0,。,例如:,0 x1A 2,。右移过程如图,2.8,所示。,例如:,0 x8AU 2,。右移过程如图,2.9,所示。,右移运算符的作用相当于将,value,的值整除以,46,赋值运算符有两种形式,一种是简单赋值运算符,另一种是复合赋值运算符。,1,简单赋值运算符,语法形式:,var=exp,2,复合赋值运算符,在进行如,x=x+3,运算时,,C#,提供一种简化方式,x+=3,,这就是复合赋值运算。,语法形式:,var op=exp /op,表示某一运算符,等价的意义是:,var=var op exp,2.3.5,赋值运算符,47,运 算 符,用 法 示 例,等价表达式,运 算 符,用 法 示 例,等价表达式,+=,x+=y,x=x+y,&=,x&=y,x=x&y,=,x,=y,x=x,y,|=,x|=y,x=x|y,*=,x*=y,x=x*y,=,x=y,x=x y,/=,x/=y,x=x/y,=,x=y,x=x y,%=,x%=y,x=x%y,=,x=y,x=x y?x:y;/z,的值就是,x,,,y,中较大的一个值,z=x=0?x:,x;/z,的值就是,x,的绝对值,条件运算符“,?:”,是,C#,中唯一一个三元运算符。,2.3.6,条件运算符,49,当一个表达式含有多个运算符时,,C#,编译器需要知道先做哪个运算,这就是所谓的运算符的优先级,它控制各个运算符的运算顺序。,例如,表达式,x+5*2,是按,x+(5*2),计算的,因为“*”运算符比“,+”,运算符优先级高。,当操作数出现在具有相同优先级的运算符之间时,如表达式“,10,6,2”,按从左到右计算的结果是,2,,如果按从右到左计算,结果是,6,。当然“,”运算符是按从左到右的次序计算的,也就是左结合。,再如表达式“,x=y=2”,,它在执行时是按从右到左运算的,即先将数值,2,赋给变量,y,,再将,y,的值赋给,x,。所以“,=”,运算符是右结合的。,在表达式中,运算符的优先级和结合性控制着运算的执行顺序,也可以用圆括号“()”显式地标明运算顺序,如表达式“,(x+y)*2”,。,2.3.7,运算符的,优先级与结合性,50,表,2.9,运算符的优先级与结合性,类 别,运 算 符,结 合 性,初等项,.()new typeof checked unchecked,从左到右,一元后缀,+,从右到左,一元前缀,+,+,!,(T)(,表达式,),从右到左,乘法,*/%,从左到右,加法,+,从左到右,移位,从左到右,关系和类型检测,=is as,从左到右,相等,=!=,从左到右,逻辑与,&,从左到右,逻辑异或,从左到右,逻辑或,|,从左到右,条件与,&,从左到右,条件或,|,从左到右,条件,?:,从右到左,赋值,=*=/=%=+=,=,=&=|=,从右到左,51,在表达式中,操作数的数据类型可以不同,只要相互兼容即可。当表达式中混合了几种不同的数据类型时,,C#,会基于运算的顺序将它们自动转换成同一类型。,下面是,C#,的类型提升规则。,(,1,)一个操作数是,decimal,类型,另一个操作数提升为,decimal,,但,float,或,double,类型不能自动提升为,decimal,。,(,2,)一个操作数是,double,类型,另一个操作数提升为,double,。,(,3,)一个操作数是,float,类型,另一个操作数提升为,float,。,(,4,)一个操作数是,ulong,类型,另一个操作数提升为,ulong,,但带符号数,如,sbyte,、,short,、,int,或,long,不能自动提升。,(,5,)一个操作数是,long,类型,另一个操作数提升为,long,。,(,6,)一个操作数是,uint,类型,另一个操作数若是,sbyte,、,short,或,int,,那么这两个操作数都提升为,long,。,(,7,)一个操作数是,uint,类型,另一个操作数提升为,uint,。,(,8,)除以上情况之外,两个数值类型的操作数都提升为,int,类型。,2.3.8,表达式中的类型转换:,52,强制类型的转换形式:,(类型)表达式,例如:,decimal d1,d2;,float f1;,d1=99.999;,f1=0.98;,d2=d1+f1;/,出错,因为,float,类型的,f1,不能自动转换成,decimal,类型,d2=d1+(decimal)f1;,注意:,1.,当从占用内存较多的数据类型向占用内存较少的数据类型做强制转换时,有可能会发生数据丢失。,例如,从,long,数据类型强制转换成,int,类型时,如果,long,类型的值超过,int,所能表示的范围,则会丢失高位数据。,2.,虽然,char,类型属于整数类型的一种,但却不允许直接将一个整型数赋给一个,char,类型的变量,,解决的方法就是用强制类型转换。,3.,布尔类型,不能,进行数据类型转换。,53,任何程序都可以且只能由三种基本流程结构构成,即顺序结构、分支结构和循环结构。,1.,顺序结构是三种结构中简单的一种。即语句按照书写的顺序依次执行;,2.,分支结构又称为选择结构,它将根据计算所得的表达式的值来判断应选择执行哪一个流程分支;,3.,循环结构则是在一定条件下反复执行一段语句的流程结构。,2.4.1,结构化程序设计的三种基本流程,图,2.10,程序设计的三种控制流程,54,分支语句就是条件判断语句,它能让程序在执行时根据特定条件是否成立而选择执行不同的语句块。,C#,提供两种分支语句结构,,if,语句和,switch,语句。,2.4.2,分支语句,1,if,语句,1.if,框架,语法形式:,if(,条件表达式,),语句;,2.if_else,框架,语法格式:,if(,条件表达式,),语句,1,;,else,语句,2,;,3.if_else if,框架,语法形式:,if(,条件表达式,1),语句,1,;,else if(,条件表达式,2),语句,2,;,else if(,条件表达式,3),语句,3,;,else,语句,n,;,4.,嵌套的,if,语句,55,switch,语句是一个多分支结构的语句,它所实现的功能与,if_else if,结构相似,但在大多数情况下,,switch,语句表达方式更直观、简单、有效。,2,switch,语句,语法形式:,switch,(表达式),case,常量,1,:语句序列,1,;,/,由零个或多个语句组成,break,;,case,常量,2,:语句序列,2,;,break,;,.,default,:,/default,是任选项,可以不出现语句序列,n,;,break,;,使用注意,(,1,),switch,语句表达式必须是整数类型,,case,常量必须与表达式类型兼容,,case,常量的值必须互异,不能有重复。,(,2,)“不穿透”规则,(,3,)可以有两个或多个,case,前缀指向相同的语句序列。,56,using System;,class StudentGrade,public static void Main(),Console.Write(,输入学生百分制的成绩:,);,int Grade=(int)Console.Read();,switch(Grade/10),case 9:,case 10:Console.WriteLine(,你的成绩为:,A);,break;,case 8:Console.WriteLine(,你的成绩为:,B);,break;,case 7:Console.WriteLine(,你的成绩为:,C);,break;,case 6:Console.WriteLine(,你的成绩为:,D);,break;,default:Console.WriteLine(,你的成绩为:,E);,break;,【,例,2.1,】,从键盘输入学生的百分制成绩,换算成等级制成绩,57,循环语句是指在一定条件下,重复执行一组语句,它是程序设计中的一个非常重要也是非常基本的方法。,C#,提供了,4,种循环语句:,while,、,do_while,、,for,和,foreach,。,foreach,语句主要用于遍历集合中的元素。,2.4.3,循环语句,1,while,语句,语法形式:,while,(条件表达式),循环体语句;,如果条件表达式为真(,true,),则执行循环体语句。,while,语句执行流程如图,2.11,所示,图,2.11 while,语句执行流程图,58,【,例,2.2,】,用,while,语句求,using System;,class StudentGrade,public static void Main(),Console.Write(,输入学生百分制的成绩:,);,int Grade=(int)Console.Read();,switch(Grade/10),case 9:,case 10:Console.WriteLine(,你的成绩为:,A);,break;,case 8:Console.WriteLine(,你的成绩为:,B);,break;,case 7:Console.WriteLine(,你的成绩为:,C);,break;,case 6:Console.WriteLine(,你的成绩为:,D);,break;,default:Console.WriteLine(,你的成绩为:,E);,break;,59,2,do_while,语句,语法形式:,do,循环体语句;,while,(条件表达式),该循环首先执行循环体语句,再判断条件表达式。如果条件表达式为真(,true,),则继续执行循环体语句。,do_while,循环语句执行流程如图,2.12,所示。,图,2.12 do_while,语句执行流程图,60,【,例,2.3,】,用,do_while,语句求,using System;,public class Sum100,public static void Main(),int Sum,i;,Sum=0;i=1;,do,Sum+=i;,i+;,while(i=100),Console.WriteLine(Sum is +Sum);,while,语句与,do_while,语句很相似,它们的区别在于,while,语句的循环体有可能一次也不执行,而,do_while,语句的循环体至少
展开阅读全文