资源描述
本资料仅供参考,不能作为科学依据。谢谢。本资料仅供参考,不能作为科学依据。本资料仅供参考,不能作为科学依据。谢谢。本资料仅供参考,不能作为科学依据。,本资料仅供参考,不能作为科学依据。谢谢。本资料仅供参考,不能作为科学依据。本资料仅供参考,不能作为科学依据。谢谢。本资料仅供参考,不能作为科学依据。,面向对象和组件C#编程,科学出版社,第二章 程序结构、变量、类型、运算符,李 军,武汉大学 测绘学院,“我成长”网站,1/71,第二章 程序结构、变量、类型、运算符,1,2,3,4,程序结构,变量、常量和字量,类型,运算符,5,运算符优先级和结合性,2/71,2.1 程序结构,在1.7节,我们编写了一个Hello控制台程序,代码以下。,using System;,using System.Collections.Generic;,using System.Linq;,using System.Text;,namespace HelloApp,class Program,static void Main(string args),Console.WriteLine(Hello!);,3/71,最简单Hello控制台程序代码,上面就是最简单Hello控制台程序代码吗?,其实代码还可简化成下面形式:,class Program,static void Main(),System.Console.WriteLine(Hello!);,它没有了前面四条using语句,,也没有了namespace,Main()中也没有参数;,但在Console前添加了“System.”。,它才是最简单Hello控制台程序代码!,4/71,2.1.1 用类比了解程序结构,房屋好比是类class,房屋名称为HappyHouse;,房屋入口是类中Main()函数。,房主拥有那块土地称为myLand,,它由namesapce定义:,namespace myLand,class HappyHouse,static void Main(),System.Console.WriteLine(Hello!);,5/71,类比,1)WriteLine可类比为其它土地(System)中房屋(Console)里面某个东西,用代码表示为:,土地.房屋.东西;,2)小数点“.”表示访问操作,比如,myLand.HappyHouse.Main(),表示:,访问myLand中HappyHouseMain组员。,HappyHouse房主并没有定义WriteLine,,但并不妨碍他借用他人东西。,他在Main中就借用了基类库BCL函数:,System.Console.WriteLine();,6/71,2.1.2 命名空间,用C#术语说,namespace关键字定义了命名空间,,大括号中东西称为类型,语法以下:,namespace 空间名称,定义类型,大括号界定了范围。空间名称要唯一,不然无法界定命名空间中类型。,类型中定义东西称为组员。以下所表示:,namespace 空间名称,类型1,组员,类型2,组员,.,7/71,命名空间-,一个分组符号,namespace 说明HelloApp是本项目标命名空间。,命名空间就是一个程序集内相关类型一个分组符号。,System,内建数据、数学计算、垃圾搜集器,System.Drawing,处理图形和绘图,包含打印,System.Data,处理数据存取和管理,ADO.NET,System.IO,管理对文件和流同时和异步访问,System.Windows,处理基于窗体窗口创建,System.Reflection,包含从程序集读取元数据类,System.Threading,包含用于多线程编程类,System.Collections,包含定义各种对象集接口和类,8/71,程序集、命名空间、类型和组员,一个程序集能够包含任意个命名空间,,每个命名空间又能够包含各种类型。,用“对象浏览器”可见:,程序集只有一个HelloApp命名空间,命名空间中类型是Program类(class),Object是Program基类;右边是Object类组员。,9/71,分析下面代码,namespace HelloApp /命名空间,int a;,/定义变量:错误!,static void Main()/定义函数:错误!,class Program,10/71,2.1.3 引用using,“引用”反应了C#编程组件思想:,尽可能使用基类库或其它成熟程序集。,using System;,说明了HelloApp项目引用(using)了System命名空间。,System命名空间中,提供了大量关键类型,,如System.Int32、string等类型,定义在,内部程序集,中,。,using简化了对特定命名空间中类型,引用方法,。,因为引用了System,所以编译器能够将Console类解析为这个命名空间组员。假如没有引用System,将出现一个编译器错误。也能够,使用完全限定名来使用Console类函数:,System.Console.WriteLine(Hello!);,11/71,系统自动添加引用-,内部程序集,许多关键.NET命名空间包含在mscorlib.dll文件中。多数.NET Framework程序集都位于全局程序集缓存GAC特定目录下(默认下C:WindowsAssembly)。在创建本项目时,系统自动添加了一些全局程序集引用,对它们引用,仅仅经过using关键字来指定命名空间即可。,12/71,引用外部程序集(do it),不在上图中列出程序集,都是外部程序集。,对外部程序集,除了经过using关键字来指定命名空间,还需要告诉C#编译器包含引用类型程序集名字。,比如,System.Drawing.Bitmap类型包含在另一个名为System.Drawing.dll程序集中。引用它方法以下:,右键点击【引用】,【添加引用】,,然后在对话框中选择System.Drawing组件;,见下列图。,13/71,添加System.Drawing.dll程序集,14/71,在Program.cs代码前添加:,using System.Drawing;,你就能够在项目中添加图形类型详细引用了,,比如在Main()中加上语句:,Bitmap Map=new Bitmap(20,20);,Bitmap是System.Drawing命名空间中一个类。,Map是Bitmap类型变量,,经过Map=new Bitmap(20,20);,语句被赋值为Bitmap对象;即调用Bitmap类结构函数Bitmap(20,20)来创建一个对象。,也可说Map是用new实例化一个Bitmap对象。,注:命名空间与程序集普通是对应,命名空间为*,,它程序集名字就为*.dll。,15/71,2.1.4 格式化输出,在Main()中添加语句:,Console.WriteLine(0,1,Hello,World!);,系统输出:“Hello,World!”字符串。,0、1标识嵌入在字符串中,,它是格式化输出方法,,与C语言printf()相同。,能够使用这种花括号在文本内部指定占位符。,在运行时,值会传入到WriteLine()来替换每一个占位符。,16/71,数据位置索引,能够在字符串文本任意位置放置占位符,而不需要按照递增次序。比如代码:,Console.WriteLine(1+0+2=3,10,20,30,60);,/数据位置索引 0 1 2 3,/输出:20+10+30=60,后面数据 10,20,30,60 位置索引总是依递增次序0,1,2,3;而占位符n中n只能是03,,0表明在占位符0上接收是索引为0数据(即10),,1上接收是索引为1数据(即20);,而0排在1后面,故10在20后面显示。,17/71,格式化数值数据,假如数值数据需要更精细格式化,每一个占位符都能够(可选)包含不一样格式字符,下表显示了关键格式化选项。,18/71,使用一些格式化标识(do it),给定占位符值以冒号为标识,将这些字符作为后缀(比如,0:C、1:d、2:X)。,修改Main()方法,添加下面语句,从而格式化一个固定值。比如:,/使用一些格式化标识,Console.WriteLine(The value 88888 in various formats:);,Console.WriteLine(c format:0:c,88888);/0代表占位符,Console.WriteLine(d9 format:0:d9,88888);/补零到9位,前补零,Console.WriteLine(f3 format:0:f3,88888);/f3 保留小数点后3位,Console.WriteLine(n format:0:n,88888);,/注意,十六进制数大小写形式决定了字母是大写还是小写。,Console.WriteLine(E format:0:E,88888);,Console.WriteLine(e format:0:e,88888);,Console.WriteLine(X format:0:X,88888);,Console.WriteLine(x format:0:x,88888);,19/71,应用程序输出 (do it),20/71,在控制台应用程序外格式化数值数据,.NET字符串格式化字符不局限于在控制台程序中使用!一样格式化语法能够在调用静态string.Format()方法时使用。,假如我们需要对任何应用程序类型(桌面GUI程序、Web程序等)在运行时组合文本数据,这个方法就很有用。在消息对话框中显示:,/使用string.Format()来格式化字符串文本,string userSt=string.Format(100 in hex is 0:x,100);,/需要引用System.Windows.Forms.dll才能编译这行代码,System.Windows.Forms.MessageBox.Show(userSt);,注意string.Format()是按照提供标志进行格式化。,至此,我们就能够任意使用需要文本数据了。,21/71,2.2 变量、常量和字量,2.2.1 变量申明,定义或申明变量方法以下:,类型 var_name;,类型 var_name=初值;,其中var_name是变量名称(标识符)。,注:假如是在类中定义变量,,申明时可加修饰符(细节见后面章节),22/71,2.2.3 变量种类和赋值,2.2.2 变量命名(自学),变量分为八种类别:,静态、非静态变量、数组元素、局部变量,值参数、引用参数、输出参数、数组参数。,注意:在C#中,不能定义全局变量。,【例2-3】变量种类。,class Program /类,int x=1;/x是非静态变量,public static int y=2;/y是静态变量,void f(int s,int val,ref int i,out int j)/数组s,值参数val,int w=2;/w是局部变量,j=x+y+i+w;/j是输出参数,x是非静态变量,y是静态变量,s是数组,,val是值参数,i是引用参数,j是输出参数。,23/71,2.2.4 常量和字量,常量申明语法为:,修饰符 const 类型 ConstName;,在申明常量时,要用到const关键字。,下面是一个申明常量例子:,public const double PI=3.1415926;,字量,字量就是类型字面值。它与常量本质上相同,但它愈加简单:不用申明,把值直接写出来即可。比如,下面语句中出现123就是整数字量:,int i=123;,24/71,字符串字量,string s3=“Hello n World!”;/串包含转义序列n,换行,Console.WriteLine(0,s3);,运行结果:,Hello,World!,逐字字符串字量,逐字字符串字量由字符和后面双引号中多个字符组成,假如包含转义序列或Unicode字符,都作为普通字符处理。即“转义”失效。比如:,string s1=Hello World!;/有字符串,string s2=Hello n World!;,/串包含转义序列n,但作为二个普通字符处理,即:和n,Console.WriteLine(0 1,s1,s2);,运行结果:,Hello World!Hello n World!,25/71,空字量,空字量只有一个:null。,null本质含义是没有任何值,即“空”。,null不属于任何类型,但它可隐式地转换为任何可接收空值类型,如引用类型。,字符串和object都是引用类型,,所以下面语句是正确:,string st=null;/null不等价于无字符串,object obj=null;/表示obj没有任何值,26/71,可空类型 int?,但下面语句不正确:,int i=null;,简单类型不是可空类型,,所以int类型变量不接收null,所以C#提供了“可空类型”这种语法,,只要在任何“不可空”类型后加?就组成了可空类型,如“int?”,所以下面语句是正确:,int?i=null;,float?f=null;,27/71,2.3 类型,计算机科学家Wirth提出过一个公式:,算法+数据结构=程序,数据结构在.NET中形式就是公共类型系统,简称类型(Type)。,一个变量用于连接一个名称(变量名),和一小块内存。,一个变量有它值,也就是这小块内存中存放值。,至于这小块内存大小,,以及怎样解释其中存放数据,是和变量类型相关。,28/71,整个C#类型系统,29/71,2.3.1 类型分类,1)值类型和引用类型(分类方法1),假如按变量存放是数据还是数据引用来区分,C#类型(或CTS)可分为值类型和引用类型,见下列图。,30/71,深入划分,值类型深入划分:,简单类型(simple type),枚举类型(enum type),结构类型(struct type),引用类型深入划分:,类类型(class type),接口类型(interface type),数组类型(array type),委托类型(delegate type),字符串类型(string type),31/71,代码例子,值类型变量直接包含它们数据,,而引用类型变量存放是它们数据引用(即对象引用)。比如:,int i=1;/i是值类型变量,1 直接存放在i中。,object obj=new object();,obj是引用类型变量,,obj存放是对象引用。,32/71,怎样了解引用类型,“引用类型到底是什么东西啊?”我们用比喻法往返答您问题。,计算机内存是用于存放数据,所以内存好比是房屋。,只有二种房屋:一个是“堆”,另一个是“栈”。,但每种房屋会有许多房间,用“房间号”区分它们,“房间号”其实就是内存地址。,double x=12.3;/x是值类型变量,12.3直接存放在x中。,double y=x;/y是值类型变量,y=x造成12.3存放在y中。,string s1=new string(w,3);/s1是引用类型变量,s1存放是地址0 x01-对象引用。,string s2=Hello;,/s2存放是地址0 x02对象Hello引用。,string s3;,/s3是引用类型变量,s3什么也没有存放。,string s4=s2;,/s4=s2,造成地址0 x02存放在s4中。,33/71,内建系统类型和自定义类型,(分类方法2),假如按类型是系统定义好还是用户自定义来区分,C#类型可分为内建系统类型和自定义类型。有5种C#类型可由用户自定义:,类类型、结构类型、接口类型、枚举类型和委托类型。,其它都是系统内建好,用户可直接使用。,内建系统类型=简单类型+两个引用类型(string和object类,),34/71,C#内建系统类型,35/71,CLS类型,注:符合CLS类型能够被任何托管编程语言使用。假如你程序中出现了不符合CLS数据,,那么其它语言可能就不能使用它们。,上表中,有一列(系统类型)专门给出了每种类型完整名称。C#全部基本类型都有一个短名称和一个完整名称。完整名称对应于BCL中命名类型。这个名称在全部语言中都是相同。,其实从编译器角度看,两种名称是完全一样,最终都将生成一样代码。,36/71,自定义值类型(枚举和结构),其它“自定义类型”见第3章之后内容,1),枚举,枚举类型是一组命名常数值类型。,下面Color枚举类型有三个命名常数:,Red、Green和Blue;它们值分别为0、1和2。,enum Color,Red,Green,Blue,即使数值0、1、2代表三种颜色,,但用命名(Red、Green、Blue)显然要好些,,名称更加好记忆与了解。,这正是我们用枚举原因所在。,37/71,下面程序演示了枚举使用方法,class Program,enum Color /定义枚举,Red,Green,Blue,static void Main(string args),Color myc=Color.Green;/给枚举变量赋值,switch(myc)/判断枚举变量是什么值,case Color.Red:,Console.WriteLine(red value=0,(int)myc);,break;,case Color.Green:,Console.WriteLine(green value=0,(int)myc);,break;,case Color.Blue:,Console.WriteLine(blue value=0,(int)myc);,break;,38/71,2)结构,像类一样,结构能够包含数据组员和函数组员;,与类不一样是:结构是值类型(不用分配堆),,结构类型变量直接保留结构数据,,而不是对象引用。,结构普通定义为:,修饰符 struct 结构名,/下面是结构体,用于定义结构组员,修饰符 类型 字段;/数据组员,修饰符 类型 方法()/方法,39/71,结构存在原因,普通情况下,用类即可满足要求;,但假如要求程序性能高(运行快,节约空间),,对于小数据结构,用结构能够节约存放空间。,这正是结构存在原因所在。,下面定义了点结构:,struct Point,public int x,y;,public Point(int x,int y),this.x=x;this.y=y;,40/71,使用结构代码片段以下:,Point p1=new Point(10,10);/给结构变量赋值,Point p2=p1;/赋值使p2建立了一个p1副本,p1.x=100;/修改p1.x,但p2.x不会受影响,假如用类定义Point,,则p2=p1语句使p1和p2变量引用同一个对象,,当修改p1值(p1.x=100),,p2.x也发生了改变。,这正是值类型与引用类型差异。,41/71,可空类型和不可空类型,(分类方法3),假如按类型是否接收null值来区分,C#类型可分为,可空类型(Nullable)和不可空类型。,引用类型是可空类型,而其它是不可空类型。,但C#提供了一个“可空类型”语法,只要在任何不可空类型后加“?”,就组成了可空类型,如“int?”、“bool?”,所以下面语句是正确:,int?i=null;/null,不等价于,0,string st=null;/null不等价于无字符串,42/71,泛型和非泛型(分类方法4),泛型 见第12章,假如按类型是否接收参数来区分,C#类型可分为,泛型(generic)和非泛型。,泛型引入了类型参数,由一个泛型能够派生出许多特定类型。,“可空类型”语法其实就是泛型,System.Nullable简写,其中T是参数。,int?,是System.Nullable简写。,下面二条语句是等价:,int?,i=null;,System.Nullable,j=null;,43/71,2.3.2 简单类型(系统定义值类型),简单类型包含数值类型以及bool和char类型。,内容见教材,请自学,2.3.4 结构类型(自定义值类型),内容见教材,请自学,44/71,2.3.5 字符串,(系统定义引用类型),【例2-10】字符串操作:“加”法,取子字符串,替换,插入等。,static void Main(),string s1=小鸟;/定义一个字符串变量s1,并赋值,string s2=s1+翱翔;/字符串“加”法,/结果:s2=小鸟翱翔,string s3=s2.Substring(1,3);/从字符串开始位置1,取得长度为3子串,/结果:s3=鸟翱翔,s3=s2.Replace(翱翔,自由);/把s2中子串 翱翔 替换为 自由,/结果:s3=小鸟自由,s3=s3.Insert(2,-);/从位置2,插入字符串-,/结果:s3=小鸟-自由,bool isEqual=(s1=s2);/判断二个字符串是否相等,/结果:isEqual=false,bool isContain=s2.Contains(鸟翱翔);/判断s2中是否包含某字符串,/结果:isContain=true,/静态方法Format,格式化一个字符串,它与控制台程序格式化是相同。,s1=string.Format(小鸟飞了0公里,9);,/结果:s1=小鸟飞了9公里,45/71,部分string方法和属性,46/71,2.3.6 数组(自定义引用类型),数组是一个含有相同类型和名称变量集合,如一组整数、一组字符等。,1)一维数组,一维数组类型语法是在“非数组类型”后放方括号,普通形式为:,非数组类型,int a;,/申明了一个数组变量a,初值null,a还没有分配内存空间。,a=new int2;,/在堆上分配了有2个整数单元内存,其地址赋给了变量a,a0=6;a1=4;/对数组元素进行赋值。,47/71,2)多维数组(矩形数组),普通形式为:,非数组类型n个逗号,n个逗号表示是数组维度,即n+1维数组。比如,int,表示二维整数数组类型,而下面语句申明了一个二维数组b:,int,b=new int3,2 1,2,3,4,5,6 ;,或:int,b=new int3,2 1,2,3,4,5,6;,48/71,2.3.7 object类型(系统定义引用类型),全部结构类型隐式地继承object类型,,这么任何类型值都能够被处理成对象。,值类型值能够经过执行装箱(boxing)操作处理为对象,也可用取消装箱unboxing,,把object对象还原成值类型值。,int i=123;,object obj=(object)i;/装箱,int j=(int)obj;/取消装箱,49/71,2.3.8 变量类型之间转换,有四种转换方式:,隐式转换、强制类型转换、ToString函数、Convert类。,1)隐式转换,若两种变量类型是兼容或者目标类型取值范围大于源类型时就能够使用隐式转换。,int i=12;,double f=i;/隐式转换成功,i=f;/不成功,因为f取值范围大于i,50/71,2)强制类型转换,强制类型转换告诉编译器:,将一个类型变量转换为另外一个类型变量。,隐式转换不能满足全部编程需要,很多时候还是需要强制类型转换。但强制转换可能产生结果不够准确。,强制类型转换语法为:,(target-type)变量或表示式;,int i=2;,double d=3.4;,int v1=(int)(i+d);/强制转换:double-int数值,51/71,3)ToString函数,ToString函数用于将变量转化为字符串,各种类型变量都能够用ToString。下面代码把int变量转为字符串:,int i=250;/i是整型变量,string s=i.ToString();,/结果:变量s值是字符串“250”,52/71,4)Convert类,ToString无法把一个字符串转为double类型值。但可使用Convert类进行显示转换。比如:,double r=Convert.ToDouble(“3.14”);,/Convert,是静态类,,ToDouble,是它函数,运行结果:r=3.14,其值是由字符串“3.14”显示转换来。,表2-9 Convert类常见函数(,见教材,),53/71,2.4 运算符,运算符是用来定义表示式操作符。,C#提供了大量运算符,从功效上可分为:,算术运算符(,+,-,*,/,%,),位运算符 (,,&,|,,),逻辑运算符(,&,|,!,),条件(赋值)运算符,(,?:,),赋值运算符,(,=,+=,-=,*=,/=,%=,,位运算符=),关系运算符(,=,!=,=,),从运算对象上能够分为:,单目运算符、双目运算符和三目运算符。,54/71,2.4.1 算术运算符和自增自减运算符,算术运算符是指对数值(如整数、小数等)进行算术运算所用运算符,包含:,加(+)、减(-)、乘(*)、除(/)、取余(%),自增和自减运算符包含:,+,-,自增运算符其实是加1简化表示法,,自减运算符是减1简化表示法。,比如x=x+1,用自增表示式表示为:,x+,或:+x,55/71,2.4.2 位运算符,位运算符有六种:,,&,|,5,/y=5 为true,但x5 为false,故a=false,结果:a=false,其它逻辑运算见教材。,58/71,2.4.4 关系运算符,关系运算符又称为比较运算符,包含:,=,!=,=,它们普通用于条件表示式中,,用来判断表示式是否符合条件。,以上运算符含义见教材表2-13。,假设x和y是double变量,如x=-6.4,y=3,,则下面都是正当关系表示式:,x y,x+3=y,(x3)!=(y=5),三个关系表示式结果分别为:false,false,true,59/71,2.4.5 条件运算符,条件运算符是C#中唯一一个三元运算符。,普通形式为:,?:,假如满足条件就执行表示式1,不然执行表示式2。,条件运算符常惯用于条件赋值,普通形式为:,变量=?:,int b,x=6,y=4;,b=(y 一元 算术 移位 关系,按位 逻辑 赋值,表示优先级高于。,运算符中一元运算符(!等)是例外,,其它都遵照这个规律。,67/71,2.5.2 运算符结合性,结合性表示:,当优先级相同时候,,按照运算符结合方向确定运算次序。,运算符结合性分为两种方式:,左结合(从左到右),右结合(从右向左),左结合-从左到右,是普通方式。,比如算术运算符:,+,-,*,/,68/71,结合性,只有三个运算符是从右至左结合,它们是:,一元运算符、条件运算符、赋值运算符。,其它都是从左至右结合。,从左至右结合:,x=10/2*5;/等价于 x=(10/2)*5;,赋值运算符从右至左结合:,x=y=3;/等价于 y=3;x=y;,点运算是自左向右结合,,所以a.b.c含义是(a.b).c而不是a.(b.c)。,System.Console.Write(OK);/等价于:(System.Console).Write(OK);,69/71,2.6 编程练习,1 编程要求,编写一个控制台程序,程序能够从键盘读一组正整数,读到-1结束;程序对输入一组正整数进行计数,并统计最大和最小数,最终输出它们。,2 编程关键点,编程要用循环语句(while)等候用户从键盘输入,用条件语句(if)判断不一样情况,做不一样处理,然后用控制台WriteLine函数输出结果。,70/71,感激!,71/71,
展开阅读全文