《C#入门教学经典教程》由会员分享,可在线阅读,更多相关《C#入门教学经典教程(433页珍藏版)》请在金锄头文库上搜索。
1、C#C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。并定于在微软职业开发者论坛(PDC)上登台亮相。C#是微软公司研究员Anders Hejlsberg的最新成果。C#看起来与Java有着惊人的相似;它包括了诸如单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。但是C#与Java有着明显的不同,它借鉴了Delphi的一个特点,与COM(组件对象模型)是直接集成的,而且它是微软公司 .NET windows网络框架的主角。 C#使得C+程序员可以高效的开发程序,且因可调用由 C/C+ 编写的本机原生函数,因此绝不损失C/C+原有的
2、强大的功能。因为这种继承关系,C#与C/C+具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。第第1章章C#与与NET平台介绍平台介绍本章目标本章目标了解了解.NETFramework的结构的结构理解理解.NETFramework的基本概念的基本概念CLRJITCTSMSIL了解了解.NETFramework命名空间命名空间了解了解C#程序的基本结构程序的基本结构1C#语言的由来语言的由来在过去的二十年里,C和C+已经成为在商业软件的开发领域中使用最广泛的语言。它们为程序员提供了十分灵活的操作,不过同时也牺牲了一定的开发效率。与VB等语言相比,同等级别的C/C+应用程序往往需要更长时间
3、来开发。由于C/C+语言的复杂性,许多程序员都试图寻找一种新的语言,希望能在功能与效率之间找到一个更为理想的权衡点。VB以牺牲灵活性的代价来提高效率。可是这些灵活性正是C/C+程序员所需要的。这些解决方案对编程人员的限制过多(如屏蔽一些底层代码控制的机制),所提供的功能难以令人满意。这些语言无法方便地同早先的系统交互,也无法很好地和当前的网络编程相结合。对于C/C+用户来说,最理想的解决方案无疑是在快速开发的同时又可以调用底层平台的所有功能。他们想要一种和最新的网络标准保持同步并且能和已有的应用程序良好整合的环境。另外,一些C/C+开发人员还需要在必要的时候进行一些底层的编程。C# (C sh
4、arp) 是对这一问题的解决方案。C#是一种新的、面向对象的编程语言。它使得程序员可以快速地编写各种基于Microsoft .NET平台的应用程序,Microsoft .NET提供了一系列的工具和服务来最大程度地开发利用计算与通讯领域。 C#语言的特点:C#语言是Microsoft发布的一种全新的编程语言,是其.Net战略的一枚重要棋子。C#语言是面向对象的、现代的编程语言,用C#编写的应用程序可以充分利用.Net的框架体系带来的优点.既可以用来编写基于通用网络协议的Internet服务软件,也可以编写各种数据库、网络服务应用程序和Windows窗口界面程序。C#继承了C/C+的优点和灵活性,
5、能够充分利用OS系统的底层功能,同时又具备了完全的面向对象特性。可以让初学者直接了解面向对象编程的各种概念,学习现代的编程思想和手段。代码代码代码代码被执行被执行被执行被执行编译器编译器编译器编译器可执行可执行代码代码可执行可执行代码代码RUNTIMERUNTIME2.NET代码的编译代码的编译语言特定的编译器和运行库语言特定的编译器和运行库代码代码代码代码被执行被执行被执行被执行编译器编译器编译器编译器可执行可执行代码代码可执行可执行代码代码RUNTIMERUNTIMEIL+元数据CLRIL和和CLR的使用的使用IntermediateLanguageCommonLanguageRuntim
6、e编译执行 .NET 程序MSIL+元数据元数据机器机器代码代码代码代码被执行被执行CLR第一次编译第一次编译第二次编译第二次编译.NET程序被编译两次,第一次编译很慢,而第二次程序被编译两次,第一次编译很慢,而第二次编译较快!编译较快!语言语言编译器编译器.NET源源代码代码Microsoft中间语言中间语言MSIL+元数据机器代码代码 被执行CLRMSIL帮助语言实现互操作IL 不是字节代码,但很接近字节代码。因此,执行应用程序时,IL 到机器码的转换速度非常快!通过 CLR将 MSIL 转换为具体 CPU 的代码CPU 无关的指令集语言语言编译器编译器.NET 源代码程序集程序集modu
7、leILIL语言范例语言范例IL_0000:nopIL_0001:callIL_0006:nopIL_0007:ldc.i4.0IL_0008:callIL_000d:nopIL_000e:ldnullIL_000f:ldftnIL_0015:newobjIL_001a:callIL_001f:nopIL_0020:newobjIL_0025:callIL_002a:nopIL_002b:newobjIL_0030:throw通用语言运行时通用语言运行时CLRCLR.NET 源代码MSIL+元数据机器代码代码被执行管理内存易于设计组件和应用程序,其对象可以跨语言互动跨语言集成(特别是跨语言继承
8、)JIT 编译器:一次编译,就可运行在支持运行库的任何 CPU 和操作系统上语言语言编译器编译器.NET的语言互操作性:的语言互操作性:不同语言编写的代码可互相调用不同语言编写的代码可互相调用C#的平台移植性:的平台移植性:框架框架JIT编译器编译器(JustInTime,即时编译器即时编译器)3.NETFramework简介简介.NETFramework类似于类似于JVM.NETFramework两个主要组件:两个主要组件:通用语言运行时通用语言运行时(CLR)统一的类库集统一的类库集.NET的类库的类库:线程线程文件输入文件输入/输出输出(I/O)数据库支持数据库支持XML解析解析数据结构
9、数据结构.NET Framework 的体系结构VisualStudio.NETVisualStudio.NETCLRCLR通用语言运行时通用语言运行时(CLR)BaseClassLibrary:BaseClassLibrary:IO, Drawing, ThreadingDataandXMLDataandXMLXMLWebXMLWebservicesservicesWindowsFormsWindowsFormsWebFormsWebForms通用语言规范通用语言规范通用语言规范通用语言规范(CLS)(CLS)VBVBC+C+C#C#JScriptJScript操作系统操作系统.NetFra
10、mework类类库库(FCL)CLS和和CTS通用语言规范通用语言规范CLS CommonLanguageSpecification规定所有规定所有.NET语言都应语言都应遵循的规则遵循的规则生成可与其他语言互操作生成可与其他语言互操作的应用程序的应用程序通用类型系统通用类型系统(CommonTypeSystem,CTS)包含标准数据类型包含标准数据类型包含准则集包含准则集CLS、CTS和和MSIL紧密配合以实现语言互操作性紧密配合以实现语言互操作性命名空间就像在文件系统中一个文件夹容纳多命名空间就像在文件系统中一个文件夹容纳多个文件一样,可以看作某些类的一个容器。通个文件一样,可以看作某些类
11、的一个容器。通过把类放入命名空间可以把相关的类组织起来,过把类放入命名空间可以把相关的类组织起来,并且可以避免命名冲突。命名空间既用作程序并且可以避免命名冲突。命名空间既用作程序的的“内部内部”组织系统,也用作组织系统,也用作“外部外部”组织系组织系统(一种向其他程序公开自己拥有的程序元素统(一种向其他程序公开自己拥有的程序元素的方法)的方法)使用命名空间:使用命名空间:using类似类似#include4 命名空间1.HclassA2.HclassA3.cpp#include“1.h”#include“2.h”.3.cppclassAclassAnamespacea1classAnamesp
12、acea2classA3.csusinga1;usinga2;a1.Aa2.A常用命名空间常用命名空间命名空间命名空间说明说明System.Drawing处理图形和绘图,包括打印处理图形和绘图,包括打印System.Data处理数据存取和管理,在定义处理数据存取和管理,在定义ADO.NET技术中扮技术中扮演重要角色演重要角色System.IO管理对文件和流的同步和异步访问管理对文件和流的同步和异步访问System.Windows处理基于窗体的窗口的创建处理基于窗体的窗口的创建System.Reflection包含从程序集读取元数据的类包含从程序集读取元数据的类System.Threading包
13、含用于多线程编程的类包含用于多线程编程的类System.Collections 包含定义各种对象集的接口和类包含定义各种对象集的接口和类5创建创建“HelloWorld”应用程序应用程序单击单击“开始开始”“程序程序”“MicrosoftVisualStudio.NET2005”“MicrosoftVisualStudio.NET2005”此时将打开此时将打开VS.NET2005的起始页的起始页要创建要创建C#控制台应用程序,请从列表中选择控制台应用程序,请从列表中选择“创创建建建建”“项目项目”。此时将打开。此时将打开“新建项目新建项目”窗口窗口选择选择“VisualC#项目项目”作为项目类
14、型,选择作为项目类型,选择“控控制台应用程序制台应用程序”作为模板作为模板C#模板模板Console.WriteLine(HelloWorld);输出输出HelloWorld.csprojAssemblyInfo.csProgram.cs“HelloWorld”应用程序文件应用程序文件编译和执行编译和执行C#应用程序应用程序要生成要生成C#项目,请从菜单中选择项目,请从菜单中选择“生成生成”“生成解决方案生成解决方案”该过程将编译项目中包括的所有文件,编译结果该过程将编译项目中包括的所有文件,编译结果显示在显示在“输出输出”窗口中窗口中如果结果显示如果结果显示“生成生成:1成功或最新,成功或最
15、新,0失败,失败,0被跳过被跳过”,则说明已经成功生成,然后即可交,则说明已经成功生成,然后即可交付该应用程序付该应用程序要运行刚才生成的应用程序,请从菜单中选要运行刚才生成的应用程序,请从菜单中选择择“调试调试”“开始执行开始执行(不调试不调试)”输出结果显示在输出结果显示在VS.NET控制台窗口中控制台窗口中C#应用程序文件夹结构应用程序文件夹结构VisualStudio.NET2005创建一个与项目同名的文创建一个与项目同名的文件夹,此处为件夹,此处为“HelloWorld”该文件夹包含项目文件该文件夹包含项目文件“HelloWorld.csproj”和其他关和其他关联文件联文件每个新项
16、目都创建了每个新项目都创建了bin、obj和和Properties三个文三个文件夹。件夹。Bin和和obj这两个文件夹下都有一个这两个文件夹下都有一个Debug子目录,其子目录,其中包含可执行文件中包含可执行文件HelloWorld.exe在在“解决方案资源管理器解决方案资源管理器”中启用中启用“显示所有文件显示所有文件”选选项,可查看项,可查看“HelloWorld”项目的结构项目的结构/这是用这是用 C# 编写的一个简单的编写的一个简单的 HelloWorld程序程序usingSystem;namespaceNotepadclassHelloWorldstaticvoidMain()Con
17、sole.WriteLine(HelloWorld);声明 HelloWorld 类描述代码的注释HelloWorld 程序程序程序入口点, Main 的返回类型为 void控制台类的 WriteLine() 方法用于显示输出结果导入 System 命名空间声明命名空间 Notepad将文件保存为将文件保存为*.cs说明说明:1.程序一般包括以下几部分:程序一般包括以下几部分:名称空间的引用:使用名称空间的引用:使用using关键字指明引用的名称空间。关键字指明引用的名称空间。名称空间的声明:使用名称空间的声明:使用namespace关键字声明名称空间。关键字声明名称空间。类:使用类:使用cl
18、ass关键字声明类。关键字声明类。Main方法:方法:Main方法是方法是C#程序的入口。程序的入口。2.类中包含了程序所要用到的数据和所要执行的方法的定义。每个类中类中包含了程序所要用到的数据和所要执行的方法的定义。每个类中可以有:可以有:(1)变量声明变量声明(2)构造函数构造函数(3)方法方法(4)属性属性(5)事件事件3.一个文件中可以有一个文件中可以有1个或者多个类。个或者多个类。4.所有语句都以分号所有语句都以分号;结束。结束。ZJWCHCC#语言基础语言基础第第2章章目标目标在在C#中定义变量和常量中定义变量和常量使用使用C#中的基本数据类型中的基本数据类型理解装箱和拆箱的概念理
19、解装箱和拆箱的概念使用使用C#中的运算符,选择结构和循环结构中的运算符,选择结构和循环结构定义和使用数组,了解结构和枚举定义和使用数组,了解结构和枚举了解了解C#中的预处理指令中的预处理指令理解理解C#中常用的字符串处理方法中常用的字符串处理方法第一个第一个 C#程序程序 :HelloWorld1. using System;2. class HelloWorld3. 4. static void Main( )5. 6. Console.WriteLine(“Hello, World!”);7. 8. HelloWorld.cs第一个第一个 C#程序程序 :HelloWorld1: usin
20、g System;第第 1 行:行:usingusing关键字关键字关键字关键字用来引用用来引用用来引用用来引用.NET.NET框架类库中的资源框架类库中的资源框架类库中的资源框架类库中的资源通常在程序文件的开头使用通常在程序文件的开头使用通常在程序文件的开头使用通常在程序文件的开头使用如果程序中需要多种资源,可以使用多次如果程序中需要多种资源,可以使用多次如果程序中需要多种资源,可以使用多次如果程序中需要多种资源,可以使用多次usingusingSystemSystem命名空间命名空间命名空间命名空间SystemSystem命名空间提供了构建应用程序所需的系统统能的访命名空间提供了构建应用程
21、序所需的系统统能的访命名空间提供了构建应用程序所需的系统统能的访命名空间提供了构建应用程序所需的系统统能的访问问问问第一个第一个 C# 程序程序 :HelloWorld2: class HelloWorld3: .8: 第第 2,3,8 行:行:类类类类在在在在C#C#或其他面向对象语言中,需要编写类或其他面向对象语言中,需要编写类或其他面向对象语言中,需要编写类或其他面向对象语言中,需要编写类使用关键字使用关键字使用关键字使用关键字classclass定义一个类,类的内容放在一对定义一个类,类的内容放在一对定义一个类,类的内容放在一对定义一个类,类的内容放在一对 中中中中示例中定义了一个名为
22、示例中定义了一个名为示例中定义了一个名为示例中定义了一个名为HelloWorldHelloWorld的类的类的类的类第一个第一个 C# 程序程序 :HelloWorld4: static void Main( )5: .7: 第第 4,5,7 行:行:MainMain方法方法方法方法MainMain方法是应用程序的入口点,编译器将由该处开始执行方法是应用程序的入口点,编译器将由该处开始执行方法是应用程序的入口点,编译器将由该处开始执行方法是应用程序的入口点,编译器将由该处开始执行程序程序程序程序方法体也放在一对方法体也放在一对方法体也放在一对方法体也放在一对中中中中每个每个每个每个C#C#的应
23、用程序都必须包含的应用程序都必须包含的应用程序都必须包含的应用程序都必须包含MainMain方法方法方法方法4: static void Main( )5: .7: 第第 4,5,7 行:行:MainMain方法方法方法方法 staticstatic表示表示表示表示MainMain方法是一个全局方法方法是一个全局方法方法是一个全局方法方法是一个全局方法voidvoid表示表示表示表示MainMain方法没有任何返回值,即返回值是空方法没有任何返回值,即返回值是空方法没有任何返回值,即返回值是空方法没有任何返回值,即返回值是空参数放在小括号中定义。此处括号内没有内容,表明参数放在小括号中定义。此
24、处括号内没有内容,表明参数放在小括号中定义。此处括号内没有内容,表明参数放在小括号中定义。此处括号内没有内容,表明MainMain方法方法方法方法没有任何参数没有任何参数没有任何参数没有任何参数第一个第一个 C# 程序程序 :HelloWorld6: Console.WriteLine(“Hello, World!”);第第 6 行:行: 语句语句语句语句在在在在C#C#中要执行的指令中要执行的指令中要执行的指令中要执行的指令语句之间用;分隔,编译器通过分号来区分多个语句语句之间用;分隔,编译器通过分号来区分多个语句语句之间用;分隔,编译器通过分号来区分多个语句语句之间用;分隔,编译器通过分号
25、来区分多个语句使用大括号使用大括号使用大括号使用大括号标识某个代码块的开始和结束,从而可以对语标识某个代码块的开始和结束,从而可以对语标识某个代码块的开始和结束,从而可以对语标识某个代码块的开始和结束,从而可以对语句进行组合。大括号必须成对匹配。句进行组合。大括号必须成对匹配。句进行组合。大括号必须成对匹配。句进行组合。大括号必须成对匹配。第一个第一个 C# 程序程序 :HelloWorld6: Console.WriteLine(“Hello, World!”);第第 6 行:行: 语句语句语句语句 HelloWorldHelloWorld程序的主要目的就是在屏幕上显示一条问候程序的主要目的
26、就是在屏幕上显示一条问候程序的主要目的就是在屏幕上显示一条问候程序的主要目的就是在屏幕上显示一条问候 WriteLineWriteLine方法用来将问候语写到标准输出设备上。方法用来将问候语写到标准输出设备上。方法用来将问候语写到标准输出设备上。方法用来将问候语写到标准输出设备上。 ConsoleConsole代表标准输出设备代表标准输出设备代表标准输出设备代表标准输出设备-屏幕,它属于屏幕,它属于屏幕,它属于屏幕,它属于SystemSystem命名空间命名空间命名空间命名空间 WriteLineWriteLine方法是方法是方法是方法是ConsoleConsole类的方法。访问类或对象的方法
27、使用类的方法。访问类或对象的方法使用类的方法。访问类或对象的方法使用类的方法。访问类或对象的方法使用 点取符点取符点取符点取符. .来完成。来完成。来完成。来完成。 字符串用双引号字符串用双引号字符串用双引号字符串用双引号“”“”表示表示表示表示 字符串字符串字符串字符串“ “Hello,World”Hello,World”是是是是WriteLineWriteLine方法的参数,表示屏幕输方法的参数,表示屏幕输方法的参数,表示屏幕输方法的参数,表示屏幕输出出出出 的内容的内容的内容的内容第一个第一个 C# 程序程序 :HelloWorld系统预定义类型系统预定义类型类型类型描描述述范围范围/精
28、度精度例子例子object所有其它类型的最根本的基础所有其它类型的最根本的基础类型类型objecto=null;string字符串类型,一个字符串是一字符串类型,一个字符串是一个个Unicode字符序列字符序列strings=Hello;sbyte8-bit有符号整数类型有符号整数类型128.127sbyteval=12;short16-bit有符号整数类型有符号整数类型32,768.32,767shortval=12;int32-bit有符号整数类型有符号整数类型2,147,483,648.2,147,483,647intval=12;long64-bit有符号整数类型有符号整数类型9,22
29、3,372,036,854,775,808.9,223,372,036,854,775,807longval1=12;longval2=34L;byte8-bit无符号整数类型无符号整数类型0.255byteval1=12;byteval2=34U;ushort16-bit无符号整数类型无符号整数类型0.65,535ushortval1=12;ushortval2=34U;uint32-bit无符号整数类型无符号整数类型0.4,294,967,295uintval1=12;uintval2=34U;系统预定义类型系统预定义类型类型类型描描述述范围范围/精度精度例子例子ulong64-bit无符
30、号整数类型无符号整数类型0.18,446,744,073,709,551,615ulongval1=12;ulongval2=34U;ulongval3=56L;ulongval4=78UL;float单精度浮点数类型单精度浮点数类型1.51045至至3.41038,7位精度位精度floatval=1.23F;double双精度浮点数类型双精度浮点数类型5.010324至至1.710308,15位精度位精度doubleval1=1.23;doubleval2=4.56D;bool布尔类型类型布尔类型类型;一个布尔类型数据一个布尔类型数据不是真就是假不是真就是假true,falseboolval
31、1=true;boolval2=false;char字符类型字符类型;一个字符数据是一个一个字符数据是一个Unicode字符字符charval=h;decimal精确十进制类型,有精确十进制类型,有28个有效位个有效位1.01028至至7.91028,28位精度位精度decimalval=1.23M;字面量字面量类型类别后缀示例/允许的值bool布尔布尔无无true或或falseint整数整数无无intx=100uint,ulog整数整数U或或Uuintx=1000ulong,ulong长整型长整型L或或llongx=100000Lulong无符号长整型无符号长整型ul,uL,Ul,UL,lu
32、,Lu,lU或或LUulongx=4324ulfloat单精度浮点数类型单精度浮点数类型F或或ffloatx=34.76Fdouble双精度浮点数类型双精度浮点数类型D或或ddoublex=763.7245Ddecimal精确十进制类型精确十进制类型M或或mdecimalx=1.544Mchar字符字符无无charx=astring字符串字符串无无string=”abc”int:intiMax=int.MaxValue;intpVal=int.Parse(“100”);shorti16=50;inti32=i16;i16=i32;错误错误i16=(short)i32;decimaldecima
33、liRate=3.9834M;iRate=decimal.Round(iRate,2);/四舍五入四舍五入iRate=decimal.Remainder(512.0M,51.0M);boolboolbt=(bool)1;/错误错误charstringpattern=“123abcd?”;boolbt;bt=char.IsLetter(pattern,3);bt=char.IsNumber(pattern,3);bt=char.IsLower(pattern,3);bt=char.IsPunctuation(pattern,7);bt=char.IsLetterOrDigit(pattern,3
34、);single,doublefloatf=24567.66f;doubled=124.45;If(Single.IsNaN(1/0)使用使用Parse转换数字字符串转换数字字符串shortshParse=Int16.Parse(100);intiParse=Int32.Parse(100);longshParse=Int64.Parse(100);decimaldParse=decimal.Parse(“99.99);floatsParse=float.Parse(“99.99);doubledParse=double.Parse(“99.99);字符串字符串字符串直接量字符串直接量stri
35、ngpath;path=”C:note.txt”;path=“C:note.txt”;字符串操作字符串操作索引字符串中的单个字符索引字符串中的单个字符stringstr=“abcd”;charc=str0;字符串连接字符串连接strings1=“Myage=“;intmyAge=28;stringcat=s1+myAge;字符串操作字符串操作抽取和定位子串抽取和定位子串stringpoem=“InXanadudidKublaKhan”;stringpoemSeg=poem.Substring(10);poemSeg=poem.Substring(0,9);intindex=poem.Index
36、Of(“I”);index=poem.LastIndexOf(“n”);比较字符串比较字符串boolisMatch;stringtitle=AncientMariner;isMatch=(title=ANCIENTAMRINER);isMatch=(title.ToUpper()=ANCIENTMARINER);isMatch=title.Equals(AncientMariner);String常用方法常用方法C#中常用的字符串处理方法:中常用的字符串处理方法:Equals():比较两个字符串的值是否相等:比较两个字符串的值是否相等ToLower():将字符串转换成小写形式:将字符串转换成小
37、写形式IndexOf():查找某个字符在字符串中的位置:查找某个字符在字符串中的位置SubString():从字符串中截取子字符串:从字符串中截取子字符串Join():连接字符串:连接字符串Split():分割字符串:分割字符串Trim():去掉字符串两边的空格:去掉字符串两边的空格实例实例将一文件名的扩展名改为将一文件名的扩展名改为.dat。例:。例:1.txt改为改为1.datusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;namespace_011classProgramstati
38、cvoidMain(stringargs)stringfilename=1.2.txt;intindexDot=filename.LastIndexOf(.);stringextendName=dat;filename=filename.Substring(0,indexDot+1);filename+=extendName;Console.WriteLine(filename);String常用方法应用常用方法应用1已有如下代码,按要求增加功能:已有如下代码,按要求增加功能:staticvoidMain(stringargs)stringemail;/电子邮件地址电子邮件地址Console.
39、WriteLine(请输入你的邮箱请输入你的邮箱:);email=Console.ReadLine();Console.WriteLine(你的邮箱是你的邮箱是0,email);需实现的功能:需实现的功能:1、输入输入yes时,程序循环执行时,程序循环执行2、兼容以下各种形式兼容以下各种形式yes(YES、yes、YeS.)3、提取邮箱的用户名提取邮箱的用户名using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace _011 class Program static v
40、oid Main(string args) while(1) string email; / 电子邮件地址 Console.WriteLine(请输入你的邮箱:); email = Console.ReadLine(); Console.WriteLine(你的邮箱是 0, email); Console.WriteLine(继续输入邮箱吗?); string input = Console.ReadLine(); if (input.ToUpper() = YES) continue; else break; while(true)String常用方法应用常用方法应用2输入一个字符串,输出每
41、个单词,重新用下划线输入一个字符串,输出每个单词,重新用下划线连接输出连接输出使用使用Split()方法分割字符串方法分割字符串使用使用Join()方法连接字符串方法连接字符串Split()方法方法分割字符串分割字符串代码分析代码分析splitStrings=inputString.Split();/将分割后的字符串使用下划线连接在一起将分割后的字符串使用下划线连接在一起joinString=string.Join(_,splitStrings);返回值为返回值为字符串数组字符串数组字符串变量名字符串变量名参数:分隔符(参数:分隔符(char型)型)返回字符串返回字符串静态方法静态方法参数参数
42、1:连接符:连接符参数参数2:字符串数组:字符串数组关键代码:关键代码:Join()方法方法连接字符串连接字符串using System;class Program static void Main(string args) string inputString; inputString = Console.ReadLine(); inputString = inputString.Trim(); string splitStrings = inputString.Split( ); string joinString = string.Join(_, splitStrings); Conso
43、le.WriteLine(joinString); 如果字符串两边有空格?如果字符串两边有空格?Format()方法方法两种输出字符串的方式:两种输出字符串的方式:stringname=李四李四;Console.WriteLine(Mynameis+name+,Iam+18);stringname=李四李四;Console.WriteLine(Mynameis 0,Iam1,name,18);格式字符串格式字符串变量列表变量列表String类的类的Format()方法用来格式化字符串方法用来格式化字符串关键代码:关键代码:record=string.Format(姓名姓名:0n出生年月出生年月
44、:1n身高身高:2n血型血型:3n星座星座:4n最喜欢的食物最喜欢的食物:5,name,birthday,height,bloodType,planet,favourFood);Console.WriteLine(n这是你的个人档案这是你的个人档案:);Console.WriteLine(record);参数与参数与WritLine()方法相似方法相似Format()的语法小结的语法小结stringmyString=string.Format(格式字符串格式字符串,参数列表参数列表);stringmyString=string.Format(0乘以乘以1等于等于2,2,3,2*3);格式字符串
45、格式字符串代表代表参数列表参数列表2乘以乘以3等于等于6包括占位符包括占位符x小结小结补充补充下划线处的下划线处的占位符占位符,输出五个成语,输出五个成语stringyi=一一;stringer=二二;stringsan=三三;stringword=string.Format(独独_无无_,_心心_意意,垂涎垂涎_尺尺,略知略知_,举举_反反_,yi,er,san);Console.WriteLine(word);stringyi=一一;stringer=二二;stringsan=三三;stringword=string.Format(独独0无无1,2心心1意意,垂涎垂涎2尺尺,略知略知01,
46、举举0反反2,yi,er,san);Console.WriteLine(word);枚举枚举accessmodifiersenum:enum_baseenumbodyclassMyAppenumFabric:intCotton=1,Silk=2,Wool=4staticvoidMain()Fabricfab=Fabric.Cotton;intfabNum=(int)fab;stringfabType=fab.ToString();Console.WriteLine(fab);整型,默认为整型,默认为int默认为默认为internal枚举和位标志枚举和位标志namespaceMyHelloApp
47、classmyAppFlagsenumFabricCotton=1,Silk=2staticvoidMain()Fabricfab1=(Fabric)3;Console.WriteLine(fab1.ToString();System.Enum的方法的方法usingSystem;namespaceApp1classmyAppenumFabricCotton=1,Silk=2staticvoidMain()stringfabStr=Cotton;if(Enum.IsDefined(typeof(Fabric),fabStr)Fabricfab=(Fabric)Enum.Parse(typeof(
48、Fabric),fabStr);Console.WriteLine(Enum.GetName(typeof(Fabric),2);变量变量static void Main(string args)/ 声明布尔型、字符串型、整型、短整型和浮点型变量 bool t = false;short n1 = 30;int n2 = 1200;string str = jeny;float n3 = 23.1f; / 显示变量值 Console.WriteLine (布尔值 = + t);Console.WriteLine (短整型值 = + n1);Console.WriteLine (整型值 = +
49、n2);Console.WriteLine (字符串值 = + str);Console.WriteLine (浮点值 = + n3);变量中存储的值取决于该变量的类型常量常量static void Main(string args)/ PI常量PIconst float _pi = 3.1415169F;/ 由地球引力引起的加速度常量,单位为 cm/s*s const float _gravity = 980;/ 钟摆的长度 int length = 60;/ 钟摆的周期 double period = 0;/ 钟摆周期的计算公式 period = 2 * _pi * Math.Sqrt(l
50、ength / _gravity);Console.WriteLine (钟摆的周期为 0 秒, period);声明常量在表达式中使用常量const 关键字用于声明常量数组数组数组是同一数据类型的一组值数组是同一数据类型的一组值数组属于引用类型,因此存储在堆内存中数组属于引用类型,因此存储在堆内存中数组元素初始化或给数组元素赋值都可以在声数组元素初始化或给数组元素赋值都可以在声明数组时或在程序的后面阶段中进行明数组时或在程序的后面阶段中进行语法语法: 数据类型数据类型, 数组名称数组名称 = new 类型类型 n,; int arrayHere = new int 6;数组数组static
51、void Main(string args)int count;Console.WriteLine(“请输入准备登机的乘客人数 );count=int.Parse(Console.ReadLine();/ 声明一个存放姓名的字符串数组,其长度等于乘客人数 string names = new stringcount;/ 用一个 for 循环来接受姓名 for(int i=0; i检检查查一一个个数数是是否否大大于于另一个数另一个数 操作数操作数1操作数操作数2检检查查一一个个数数是是否否小小于于另一个数另一个数 操作数操作数1=检检查查一一个个数数是是否否大大于于或等于另一个数或等于另一个数
52、操作数操作数1=操作数操作数2=检检查查一一个个数数是是否否小小于于或等于另一个数或等于另一个数 操作数操作数1=操作数操作数2=检查两个值是否相等检查两个值是否相等 操作数操作数1=操作数操作数2!=检检查查两两个个值值是是否否不不相相等等操作数操作数1!=操作数操作数2运算符和表达式运算符和表达式类别类别运算符运算符说明说明表达式表达式成员访问运算符成员访问运算符.用于访问数据结构的成员用于访问数据结构的成员 数据结构数据结构.成员成员赋值运算符赋值运算符=给变量赋值给变量赋值 操作数操作数1=操作数操作数2逻辑运算符逻辑运算符 &对两个表达式执行逻辑对两个表达式执行逻辑“与与”运算运算
53、操作数操作数1&操作数操作数2|对两个表达式执行逻辑对两个表达式执行逻辑“或或”运算运算 操作数操作数1|操作数操作数2!对两个表达式执行逻辑对两个表达式执行逻辑“非非”运算运算!操作数操作数()将操作数强制转换为给定将操作数强制转换为给定的数据类型的数据类型 (数据类型数据类型)操作数操作数运算符和表达式运算符和表达式9-6赋值运算符赋值运算符(=)变量 = 表达式;例如:身高 = 177.5;体重 = 78;性别 = “m”;运算符和表达式运算符和表达式9-7一元运算符一元运算符(+/-)Variable+; 相当于相当于 Variable=Variable+1;Variable-; 相当
54、于相当于 Variable=Variable-1;运算符和表达式运算符和表达式运算符运算符计算方法计算方法表达式表达式求值求值结果(设结果(设X=10)+=运算结果运算结果=操作数操作数1+操作数操作数2X+=2X=X+212-=运算结果运算结果=操作数操作数1-操作数操作数2X-=2X=X-28*=运算结果运算结果=操作数操作数1*操作数操作数2X*=2X=X*220/=运算结果运算结果=操作数操作数1/操作数操作数2X/=2X=X/25%=运算结果运算结果=操作数操作数1%操作数操作数2X%=2X=X%20运算符和表达式运算符和表达式C#运算符的优先级运算符的优先级优先级优先级说明说明运算
55、符运算符结合性结合性1括号括号()从左到右从左到右2自加自加/ /自减运算符自减运算符+/-从右到左从右到左3乘法运算符乘法运算符除法运算符除法运算符取模运算符取模运算符*/%从左到右从左到右4加法运算符加法运算符减法运算符减法运算符+-从左到右从左到右5小于小于小于等于小于等于大于大于大于等于大于等于=从左到右从左到右6等于等于不等于不等于=!=从左到右从左到右从左到右从左到右7逻辑与逻辑与&从左到右从左到右8逻辑或逻辑或|从左到右从左到右9赋值运算符和快捷运赋值运算符和快捷运算符算符=+=*=/=%=-=从右到左从右到左选择结构选择结构语法:语法:if()else选择结构用于根据表达式的值
56、执行语句ifelse条件:只能是条件:只能是bool类型的值类型的值选择结构选择结构switch (“cotton”)case “COTTON”: case “cotton”: break;case 值3: case 值4: break;switchcase表达式可以是表达式可以是int、字符或、字符或字符串字符串C#不允许从一个不允许从一个case块继块继续执行到下一个续执行到下一个case块。每块。每个个case块必须以一个跳转控块必须以一个跳转控制语句制语句break、goto或或return结束结束多个多个case标签可以对应一标签可以对应一个代码块个代码块循环结构循环结构循环结构用于
57、对一组命令执行一定的次数或反循环结构用于对一组命令执行一定的次数或反复执行一组命令,直到指定的条件为真。复执行一组命令,直到指定的条件为真。循环结构的类型循环结构的类型while循环循环do循环循环for循环循环foreach循环循环条件:只能是条件:只能是bool类型的值类型的值while循环反复执行指定的语句,直到指定的循环反复执行指定的语句,直到指定的条件为真条件为真语法语法:while(条件条件)/语句语句break 语句可用于退出循环语句可用于退出循环continue语句可用于语句可用于跳过当前循环并开始下一跳过当前循环并开始下一循环循环while循环循环dowhile循环循环dow
58、hile循环与循环与while循环类似,二循环类似,二者区别在于者区别在于dowhile循环中即使条件为假循环中即使条件为假时也至少执行一次该循环体中的语句。时也至少执行一次该循环体中的语句。语法语法:do/语句语句while(条件条件)for循环循环for循环要求只有在对特定条件进行判断后才允循环要求只有在对特定条件进行判断后才允许执行循环许执行循环这种循环用于将某个语句或语句块重复执行预定这种循环用于将某个语句或语句块重复执行预定次数的情形次数的情形语法语法:for(初始值初始值;条件条件;增增/减减)/语句语句foreach循环循环2-1foreach 循环用于遍历整个集合或数组 语法:
59、foreach(数据类型数据类型元素元素(变量变量)in 集合或者数组集合或者数组)/语句语句foreach循环循环2-2staticvoidMain(stringargs)/存放字母的个数存放字母的个数intLetters=0;/存放数字的个数存放数字的个数intDigits=0;/存放标点符号的个数存放标点符号的个数intPunctuations=0;/用户提供的输入用户提供的输入stringinstr;Console.WriteLine(请输入一个字符串请输入一个字符串);instr=Console.ReadLine();/声明声明foreach循环以遍历输入的字符串中的每个字符。循环以
60、遍历输入的字符串中的每个字符。foreach(charchininstr)/检查字母检查字母if(char.IsLetter(ch)Letters+;/检查数字检查数字if(char.IsDigit(ch)Digits+;/检查标点符号检查标点符号if(char.IsPunctuation(ch)Punctuations+;Console.WriteLine(“字母个数为:字母个数为:0,Letters);Console.WriteLine(“数字个数为:数字个数为:0,Digits);Console.WriteLine(“标点符号个数为:标点符号个数为:0,Punctuations);为所有
61、计数器设置初始值接受输入对输入的每一个字符都进行循环使用了所有输入的字符之后,循环自动终止using System;public class WriteTestpublic static void Main() int array = 1, 2, 3, 4, 5 ; foreach (int item in array) Console.WriteLine(item); using System;public class WriteTestpublic static void Main() int array = 1, 2, 3, 4, 5 ; foreach (int item in arr
62、ay) item += item; Console.WriteLine(item); C#的预处理指令的预处理指令2-1预处理指令是预处理指令是C#编译器在词法分析阶段读取编译器在词法分析阶段读取的语句。这些语句可以指示编译器包含或不的语句。这些语句可以指示编译器包含或不包含某些代码,甚至可以根据预处理指令的包含某些代码,甚至可以根据预处理指令的值终止编译。值终止编译。预处理指令由字符预处理指令由字符#标识,并且字符标识,并且字符#必须是必须是该行的第一个非空字符。该行的第一个非空字符。预处理指令最常见的三个用途是:完成条件预处理指令最常见的三个用途是:完成条件编译、增加诊断来报告错误和警告、
63、定义代编译、增加诊断来报告错误和警告、定义代码域。码域。C#的预处理指令的预处理指令2-2C#预处理命令预处理命令说明说明#define#undef用于定义一个符号,后取消对一个符号得定用于定义一个符号,后取消对一个符号得定义。如果定义了一个符号,那么在义。如果定义了一个符号,那么在#if指令中指令中使用时这个符号计算为使用时这个符号计算为true。#if#elif#else#endif类似类似C#中得中得if、elseif和和else语句语句#line改变行号序列,并且可以标识该行的源文件改变行号序列,并且可以标识该行的源文件#region#endregion用于指定一个代码块,使用用于指定
64、一个代码块,使用Visualstudio.NET的大纲特性时可以展开或折叠的大纲特性时可以展开或折叠这个代码块这个代码块#error导致编译器报告一个致命错误导致编译器报告一个致命错误#warming导致编译器报告一个警告,并继续处理导致编译器报告一个警告,并继续处理#defineCLIENT#defineDEBUGusingSystem;publicclassMyApppublicstaticvoidMain()#ifDEBUG&INHOUSE#warningDebuginon.#elifDEBUG&CLIENT#errorDebugnotallowedinClientCode.#endif
65、控制台输入和输出控制台输入和输出数据输入数据输入(Read,ReadLine)Console.Read()方法方法Console.Read方法用来从控制台读取一个字符,其定义方法用来从控制台读取一个字符,其定义如下如下:PublicstaticintRead();Read方法返回所读取的字符的方法返回所读取的字符的Unicode编码值。编码值。注意:注意:Read方法的返回变量是方法的返回变量是32位的整数,如果需要得位的整数,如果需要得到输入的字符,则必须通过数据类型的显式转换才能得到相到输入的字符,则必须通过数据类型的显式转换才能得到相应的字符。应的字符。控制台输入和输出控制台输入和输出C
66、onsole.Read()/ReadTest.csusingSystem;publicclassReadTestpublicstaticvoidMain()inti;charch;i=Console.Read();ch=(char)i; /显式类型转换显式类型转换Console.WriteLine(i);Console.WriteLine(ch);运行结果:A65A控制台输入和输出控制台输入和输出Console.ReadLine()方法方法Console.ReadLine方法用来从控制台读取一行字符,定方法用来从控制台读取一行字符,定义如下义如下:PublicstaticstringReadL
67、ine();Read方法返回所读取一行字符的字符串。一般情况下,一方法返回所读取一行字符的字符串。一般情况下,一行输入是指从输入一个字符开始,遇到回车符号为止。行输入是指从输入一个字符开始,遇到回车符号为止。控制台输入和输出控制台输入和输出/ReadLine.csusingSystem;usingSystem.Globalization;publicclassReadTestpublicstaticvoidMain()inti;doubled;stringstr;str=Console.ReadLine();/由控制台输入整数字符串由控制台输入整数字符串i=int.Parse(str);/整数
68、字符串转换为整数整数字符串转换为整数Console.WriteLine(i);str=Console.ReadLine();/由控制台输入浮点字符串由控制台输入浮点字符串d=double.Parse(str);/浮点字符串转换为浮点数浮点字符串转换为浮点数Console.WriteLine(d);运行结果:12341234123.456123.456控制台输入和输出控制台输入和输出数据输出数据输出(WriteWriteLine)Console.Write()方法方法Console.Write方法用来向控制台输出一个字符,但控制台的光标不方法用来向控制台输出一个字符,但控制台的光标不会移到下一行
69、。其定义如下会移到下一行。其定义如下:publicstaticvoidWrite(XXXvalue);publicstaticvoidWrite(stringformat,objecto1,);注意:格式化注意:格式化format同格式化函数同格式化函数Format中的格式化串类似,其格式中的格式化串类似,其格式如下:如下:N,M:formatstring其中,字符其中,字符N表示输出变量的序号,表示输出变量的序号,M表示输入变量在控制台中所占的字表示输入变量在控制台中所占的字符空间,如果这个数字为负数,则按照左对齐的方式输出,若为正数,符空间,如果这个数字为负数,则按照左对齐的方式输出,若为
70、正数,则按照右对齐方式输出。则按照右对齐方式输出。控制台输入和输出控制台输入和输出/WriteTest.csusingSystem;publicclassWriteTestpublicstaticvoidMain()inti=32767;doubled=456.56789;/由控制台。按照十进制输出整数及浮点数由控制台。按照十进制输出整数及浮点数Console.Write(“i=0x0,8:Xtd=1,10:F3”,i,d);/由控制台。按照十六进制输出整数由控制台。按照十六进制输出整数Console.Write(“i=0x0,-8:Xtd=1,-10:F3”,i,d);输出结果:输出结果:i
71、=0x7FFFd=456.568i=0x7FFFd=456.568控制台输入和输出控制台输入和输出Console.WriteLine()方法方法Console.WriteLine方法用来向控制台输出一行字符,即方法用来向控制台输出一行字符,即WriteLine方法在输出信息之后,在信息的尾部自动添加方法在输出信息之后,在信息的尾部自动添加“rn”字符,表示回车换行。字符,表示回车换行。publicstaticvoidWriteLine(XXXvalue);publicstaticvoidWriteLine(stringformat,objecto1,);注意:格式化注意:格式化format同同
72、WriteLine中的格式化参数完全一中的格式化参数完全一样。样。控制台输入和输出控制台输入和输出/WriteLine.csusingSystem;publicclassWriteTestpublicstaticvoidMain()inti=32767;double d=456.56789;/格式化输出格式化输出Console.WriteLine(“i=0x0,8:Xtd=1,10:F3”,i,d);Console.WriteLine(“i=0x0,-8:Xtd=1,-10:F3”,i,d);Console.WriteLine(“i=0x0,-8:Dtd=1,-10:C3”,i,d);输出结果
73、:输出结果:i=0x7FFFd=456.568i=0x7FFFd=456.568i=32767d=¥456.568ZJWCHC第第3章章C#面向对象设计面向对象设计结构程序设计的不足数据与方法分离void SpeedUp(int & speed) if(speed 0)charch=pathi1;if(ch=)break;i-;dir=path.Substring(0,i);name=path.Substring(i);staticvoidMain()stringdir,name;/变量作为输出参数无须明确赋值变量作为输出参数无须明确赋值SplitPath(c:WindowsSystemhel
74、lo.txt,outdir,outname);Console.WriteLine(dir);Console.WriteLine(name);c:WindowsSystemhello.txt参数数组参数数组在不能确定需要传递多少个参数的时候可以使用params关键字指明一个可变的参数数组。数组参数的类型必须是一维数组,而且必须是形参表中的最后一个参数。数组参数始终是值传递方式进行传递,不能将params同ref和out组合。例如,下面定义一个具有例如,下面定义一个具有params参数的求平均值函数:参数的求平均值函数:publicdoubleAVG(paramsintNums)intSum=0;
75、intCount=0;foreach(intninNums)Sum+=n;Count+=1;Nums0=100;return(Sum/Count);调用该函数时,可以采用下面的语句:调用该函数时,可以采用下面的语句:Class1a=newClass1();doubled=a.AVG(13,27,33,25,78);另外,还可以传递一个实际的数组:另外,还可以传递一个实际的数组:intargs=31,41,46,53,28;doubled=a.AVG(args);args0=?3.5属性成员属性成员属性主要用于描述和维护类对象的状态。从客户端看,对属性属性主要用于描述和维护类对象的状态。从客户端
76、看,对属性的访问就好像直接访问的访问就好像直接访问public字段成员,但在类内部是通过类字段成员,但在类内部是通过类方法访问的。方法访问的。创建一个属性包括两步:创建一个属性包括两步:1.声明一个字段来存储属性值声明一个字段来存储属性值2.编写一个属性声明,提供访问接口编写一个属性声明,提供访问接口属性的建立要使用属性声明,语法如下:属性的建立要使用属性声明,语法如下:访问修饰符访问修饰符类型名类型名属性名属性名getreturn字段字段;set私有字段私有字段=value;publicclasscheckvalprivatestringp_PropVal;/声明一个私有变量声明一个私有变量
77、p_PropValpublicstringstr1/声明属性声明属性str1get/返回存储在私有变量中的属性值返回存储在私有变量中的属性值returnp_PropVal;set/存储属性值到私有变量存储属性值到私有变量if(Convert.ToString(value).Length=10)p_PropVal=value;elseConsole.WriteLine(toomanywords);可以说,属性是一种特殊的方法,但属性和方法也可以说,属性是一种特殊的方法,但属性和方法也有不同之处,主要有:有不同之处,主要有:属性不必使用圆括号,但方法一定使用圆括号。属性不必使用圆括号,但方法一定使
78、用圆括号。属性不能制定参数,方法可以指定参数。属性不能制定参数,方法可以指定参数。属性不能使用属性不能使用void类型,方法则可以使用类型,方法则可以使用void类类型。型。属性使用方法与变量相同。属性使用方法与变量相同。属性说明属性说明可以创建只读或只写属性,即只有get或set方法。可以创建静态属性,用static关键字。静态属性不与特定实例有关联,因此在静态属性的get和set方法内引用this是错误的。静态属性使用类名访问,并且,与静态属性相配合的私有字段也应该是静态的。例例3-7:publicclasscheckvalprivatestaticstringp_time=00:00:0
79、0;/静态私有字段静态私有字段publicstaticstringmytime/静态属性静态属性getreturnp_time;publicstaticstringmytime1/静态属性静态属性setp_time=value;staticvoidMain()Console.WriteLine(checkval.mytime);checkval.mytime1=10:2:22;Console.WriteLine(nowis+checkval.mytime);输出结果为:输出结果为:00:00:00nowis10:2:223.3.6 this关键字关键字this引用的是当前实例。引用的是当前实例
80、。this关键字是一个隐含引用,它隐含于每个类的成员函数中。关键字是一个隐含引用,它隐含于每个类的成员函数中。this关键字引用类的当前对象,成员通过关键字引用类的当前对象,成员通过this关键字可以知道自关键字可以知道自己属于哪一个实例。己属于哪一个实例。publicclassTest1publicstringstr;publicvoidf(stringstr)this.str=str;publicstaticvoidMain()Test1test=newTest1();test.f(aaa);静态函数没有静态函数没有this关键字。关键字。将对象作为参数传递到其他方法,例如:将对象作为参数
81、传递到其他方法,例如:publicclassTest1publicstringstr=aaa;publicvoidf(Test1test)str=bbb;Console.WriteLine(test.str);publicvoidf1()f(this);publicstaticvoidMain()Test1test=newTest1();test.f1();索引器索引器访问修饰符 数据类型 this数据类型 标识符get;set;语法参数化成员属性:包含set、get方法。与成员属性不同:它可以接受1个或多个参数使用this作为索引器的名字定义和调用索引器定义和调用索引器class Photo
82、string _title;public Photo(string title)this._title = title;public string Titlegetreturn _title;以 Title 属性表示照片将照片存放于数组 photos 中class Album/ 该数组用于存放照片Photo photos;public Album(int capacity)photos = new Photocapacity;定义和调用索引器定义和调用索引器4-2public Photo thisint indexget/ 验证索引范围if (index = photos.Length)Con
83、sole.WriteLine(索引无效);/ 使用 null 指示失败return null;/ 对于有效索引,返回请求的照片return photosindex;setif (index = photos.Length)Console.WriteLine(索引无效);return;photosindex = value;带有 int 参数的 Photo 索引器读/写索引器定义和调用索引器public Photo thisstring titleget/ 遍历数组中的所有照片foreach (Photo p in photos) / 将照片中的标题与索引器参数进行比较 if (p.Title
84、= title) return p;Console.WriteLine(未找到);/ 使用 null 指示失败return null;带有 string 参数的 Photo 索引器只读索引器定义和调用索引器定义和调用索引器static void Main(string args)/ 创建一个容量为 3 的相册Album family = new Album(3);/ 创建 3 张照片Photo first = new Photo(Jeny );Photo second = new Photo(Smith);Photo third = new Photo(“Lono);/ 向相册加载照片 fam
85、ily0 = first; family1 = second; family2 = third;/ 按索引检索Photo objPhoto1 = family2; Console.WriteLine(objPhoto1.Title);/ 按名称检索Photo objPhoto2 = family“Jeny; Console.WriteLine(objPhoto2.Title); 中级特性中级特性面向对象技术的三个核心概念: 封装:将数据和操作组合到一起,并决定哪些数据和操作对外是可见的。 继承:父类中的变量和行为,子类可以同样使用。本质是代码重用。 多态:由继承引出的一种机制,父类型的引用变量
86、可以指向子类型的对象。 封装封装封装把对象的所有组成部分组合在一起,有三个作用 隐藏类的实现细节:使用方法将类的数据隐藏起来。 迫使用户去使用一个界面去访问数据:定义程序如何引用对 象的数据,控制用户对类的修改和访问数据的程度。 使代码更好维护:类的内部实现改变,对外接口可以不变。继承继承继承提供了创建新类的一种方法,继承对开发者来说就是代码共享。 通过继承创建的子类是作为另一个类的扩充或修正所定义的一个类。 子类从超类(父类)中继承所有方法和变量。 子类和超类之间是特化与范化的关系。子类的声明子类的声明语法:子类声明:父类子类体 子类可以使用父类的protected和public可见的变量和
87、方法,就像这些变量和方法是自己定义的一样。C# 中,如果类声明时没有声明父类,那么缺省为Object 类的子类。C#中的所有类都是System.Object类的子类。C#中,子类只能继承一个父类。classCarintcolor;intdoor;intspeed;voidPushBreak()publicvoidAddOil()classTrashCar:CarclassMyAppstaticvoidMain()TrashCarmyCar=newTrashCar();myCar.AddOil();myCar.PushBreak();派生类的建立需要注意:(1).派生类会继承基类除了构造函数和析
88、构函数的所有成员。(2).派生类调用构造函数时,会先调用基类的构造函数。默认调用没有参数的构造函数。(3).用base关键字显式调用基类构造函数。classCarpublicCar(inti)classTrashCar:CarpublicTrashCar(inti)classCarpublicCar(inti)classTrashCar:CarpublicTrashCar(inti):base(i)错误错误错误错误publicCar()去掉去掉base(i)(3). 如果需要调用基类中的同名方法,应该使用”base.方法名”来调用。class Car public Car() protecte
89、d void f() Console.WriteLine(aaa); class TrashCar : Car public TrashCar() void f() Console.WriteLine(bbb); public void f1() base.f(); f(); class MyApp static void Main() TrashCar myCar = new TrashCar(); myCar.f1(); 例3-8 继承格式举例public class parent /建立基类public parent(string str) /基类带参数构造函数Console.Write
90、Line(str);public void showposition() /基类方法Console.WriteLine(基类的位置在(0,0));public class child:parent /派生子类public child():base(调用基类构造) /子类构造函数,调用基类构造函数Console.WriteLine(I am child);public void showposition() base.showposition(); /调用基类方法Console.WriteLine(派生类的位置在(10,10));在Main()方法中执行下面的代码:parent prt=new
91、parent(I am a parent);child chd= new child();prt.showposition();chd.showposition ();输出结果为:I am a parent调用基类构造I am child基类的位置在(0,0)基类的位置在(0,0)派生类的位置在(10,10)例3-9:编写一个程序,计算球,圆锥,圆柱的表面积和体积using System;namespace ConApp1public class Circleprotected double radius;public Circle(double r) radius=r;public doub
92、le GetArea()return Math.PI*radius*radius;public class Sphere:Circle/球体类public Sphere(double r):base(r)public double GetArea()return (4*base.GetArea();public double GetVolumn() return (4*Math.PI*Math.Pow(radius,3)/3);public class Cylinder:Circle/圆柱类private double height;/添加高度字段public Cylinder(double
93、r,double h):base(r)height=h;public double GetArea() return (2*base.GetArea()+2*Math.PI*radius*height); public double GetVolumn()return(Math.PI*radius*radius*height);public class Cone:Circle/圆锥类private double height;/添加高度字段public Cone(double r,double h):base(r)height=h;public double GetArea()return(M
94、ath.PI*radius*(radius+Math.Sqrt(height*height+radius*radius);public double GetVolumn()return (Math.PI*radius*radius*height/3);public class Testerpublic static void Main()Circle c1=new Circle(2);Sphere s1=new Sphere(2);Cylinder cd1=new Cylinder(2,10);Cone cn1=new Cone(2,10);Console.WriteLine(s1s serf
95、acearea=0, volumn=1,s1.GetArea(),s1.GetVolumn();Console.WriteLine(cd1s serfacearea=0, volumn=1,cd1.GetArea(),cd1.GetVolumn();Console.WriteLine(cn1s serfacearea=0, volumn=1,cn1.GetArea(),cn1.GetVolumn();Console.ReadLine(); 多态多态继承机制引出多态机制某一类型的引用变量可以指向该类或者其子类的对象。由于C#中System.Object类是所有类的祖先,所以可以用Object类型
96、的引用指向所有类型的对象。classCarclassTrashCar:CarCarcar=newTrashCar();Objectobj=newCar();obj=newTrashCar();3.5.2 多态性多态性是指不同的对象收到相同的消息时,会产多态性是指不同的对象收到相同的消息时,会产生不同动作。生不同动作。C#支持两种类型的多态性:支持两种类型的多态性:(1)编译时的多态性是通过重载类实现的,系统在)编译时的多态性是通过重载类实现的,系统在编译时,根据传递的参数个数、类型信息决定实现编译时,根据传递的参数个数、类型信息决定实现何种操作。何种操作。(2)运行时的多态性是指在运行时,根据
97、实际情况)运行时的多态性是指在运行时,根据实际情况决定实现何种操作。决定实现何种操作。C#中运行时的多态性通过虚中运行时的多态性通过虚函成员实现。函成员实现。编译时多态编译时多态-重载重载重载指在同一个类中至少有两个方法用同一个名字,但有不同重载指在同一个类中至少有两个方法用同一个名字,但有不同的参数。的参数。重载使得从外部来看,一个操作对于不同的对象有不同的处理重载使得从外部来看,一个操作对于不同的对象有不同的处理方法。方法。调用时,根据参数的不同来区别调用哪个方法。调用时,根据参数的不同来区别调用哪个方法。方法的返回类型可以相同或不同,但它不足以使返回类型变成方法的返回类型可以相同或不同,
98、但它不足以使返回类型变成唯一的差异。重载方法的参数表必须不同。唯一的差异。重载方法的参数表必须不同。 classCarintcolor;intdoor;intspeed;publicvoidPushBreak()speed=0;publicvoidPushBreak(ints)speed-=s;Carcar=newCar();car.PushBreak();car.PushBreak(2);运行时多态运行时多态-动态绑定动态绑定(虚函数虚函数)动态绑定就是根据动态绑定就是根据对象的类型对象的类型决定调用哪个方法,而不是决定调用哪个方法,而不是引用的类型。引用的类型。类的方法使用类的方法使用vi
99、rtual关键字修饰后就成为虚方法,包括关键字修饰后就成为虚方法,包括两个步骤:两个步骤:(1).对于基类中要实现多态性的方法,用对于基类中要实现多态性的方法,用virtual关键字修饰。关键字修饰。不允许再有不允许再有static,abstract或或override修饰符。修饰符。(2).对于派生类中的同名方法对于派生类中的同名方法(覆盖覆盖)-相同的名称、返回类型相同的名称、返回类型和参数表和参数表,使用,使用override关键字修饰。不能有关键字修饰。不能有new、static或或virtual修饰符。修饰符。多态多态-覆盖覆盖C# 中声明覆盖时,父类方法前加virtual关键字,表
100、示该方法可以被覆盖;子类方法前加override,表示将方法覆盖。当用于子类的行为与父类的行为不同时,覆盖机制允许子类可以修改从父类继承来的行为。 例3-11下面的代码中,子类重写了父类的虚方法sleep()。 public class animal /基类public virtual void sleep() /虚方法Console.WriteLine(animal all need sleep);public class fish:animal /派生类public override void sleep() /重写虚方法 Console.WriteLine(fish sleeping w
101、ith eye_open);public class dog:animal /派生类public override void sleep() /重写虚方法 Console.WriteLine(dog sleeping with eye_closed);Main()中的代码:animal an=new animal3;an0=new animal();an1=new fish();an2=new dog();an0.sleep();an1.sleep();an2.sleep();输出结果:输出结果:animalallneedsleepfishsleepingwitheye_opendogslee
102、pingwitheye_closed实现多态性的核心和实质:实现多态性的核心和实质:使用基类的引用指向派生类的对象,当程序运行时,编译器会使用基类的引用指向派生类的对象,当程序运行时,编译器会自动确定基类对象的实际运行时类型,并根据实际类型调用正自动确定基类对象的实际运行时类型,并根据实际类型调用正确的方法。确的方法。例3-12class GeometricObjectpublic virtual void draw()Console.WriteLine(GeometricObject!);class Ellipse:GeometricObjectpublic override void dr
103、aw()Console.WriteLine(Ellipse!);public void getvecter()class Circle:Ellipsepublic override void draw()Console.WriteLine(Circle!);public double getArea()return 1.0;main()函数中的代码GeometricObject g=new Circle();/父类型引用指向子类型对象g.draw();g.draw(); /draw调用的是哪个类的方法?如果g换成Circle类引用呢? /如果Circle类不覆盖draw方法,调用的是哪个类的方
104、法?double d=g.getArea(); / 编译时能否通过。运行结果:运行结果:Circle!Circle!重载和覆盖的区别重载和覆盖的区别相同点:相同点:都涉及两个同名的方法。都涉及两个同名的方法。不同点:不同点:1.类层次类层次(1).重载涉及的是同一个类的两个同名方法;重载涉及的是同一个类的两个同名方法;(2).覆盖涉及的是子类的一个方法和父类的一个方覆盖涉及的是子类的一个方法和父类的一个方法,这两个方法同名。法,这两个方法同名。2.参数和返回值参数和返回值(1).重载的两个方法具有不同的参数,可以有不同返回值重载的两个方法具有不同的参数,可以有不同返回值类型;类型;(2).覆盖
105、的两个方法具有相同的参数,返回值类型必需相覆盖的两个方法具有相同的参数,返回值类型必需相同。同。方法的隐藏方法的隐藏若覆盖时没有使用virtual和override关键字,则称子类的方法隐藏了父类的方法。此时编译器报警告。若要消除掉警告,可以使用new修饰符。C# 会根据引用的类型决定调用哪个类的方法。例3-14对例3-12的方法隐藏class GeometricObjectpublic void draw()Console.WriteLine(GeometricObject!);class Ellipse:GeometricObjectpublic new void draw()Consol
106、e.WriteLine(Ellipse!);public void getvecter() class Circle:Ellipsepublic double getArea()return 1.0;main()函数中的代码GeometricObject g=new Circle();/父类型引用指向子类型对象g.draw();g.draw(); /draw调用的是哪个类的方法?如果g换成Circle类引用呢?Circle c = new Circle();c.draw();/将类Ellipse中draw()的修饰符改为private后,c.draw()的结果? 运行结果:运行结果:Geome
107、tricObject!GeometricObject!Ellipse!Ellipse!关键字new和override的区别:(1).new修饰的方法表示显式隐藏基类继承的同名方法,不能够用基类的引用访问派生类的new方法。(2).override表示重写基类的虚方法,可以用基类的引用指向派生类对象来访问派生类的重写方法。虚属性虚属性由于属性的本质就是类中的方法实现,所以,不但能够实现虚方法,还能够实现虚属性。下面代码中实现一个虚属性round。public class Square /基类public double x;public Square(double x) /构造方法this.x =
108、 x;public virtual double Area() /虚方法return x*x; public virtual double round /虚属性get return (4*x); publicclassCube:Square/派生类派生类publicCube(doublex):base(x)/构造方法构造方法publicoverridedoubleArea()/重写方法重写方法return(6*(base.Area();publicoverridedoubleround/重写属性重写属性getreturn(3*base.round);例3-13利用多态性重新实现例3-9usin
109、g System;namespace ConApp1public class Circle /基类protected double radius;public Circle(double r)radius=r; public virtual double GetArea() return Math.PI*radius*radius;public virtual double GetVolumn() return 0.0;public class Sphere:Circle/球体类public Sphere(double r):base(r)public override double GetA
110、rea() return (4*base.GetArea();public override double GetVolumn() return (4*Math.PI*Math.Pow(radius,3)/3);public class Cylinder:Circle/圆柱类 private double height;/添加高度字段 public Cylinder(double r,double h):base(r)height=h; public override double GetArea() return (2*base.GetArea()+2*Math.PI*radius*heig
111、ht); public override double GetVolumn() return (Math.PI*radius*radius*height);public class Cone:Circle/圆锥类 private double height;/添加高度字段 public Cone(double r,double h):base(r)height=h; public override double GetArea() return (Math.PI*radius* (radius+Math.Sqrt(height*height+radius*radius); public ove
112、rride double GetVolumn() return (Math.PI*radius*radius*height/3); public class Testerpublic static void Main()Circle c=new Circle3;/建立基类数组c0=new Sphere(2);c1=new Cylinder(2,10);c2=new Cone(2,20);Console.WriteLine(c0s serfacearea=0, volumn=1,c0.GetArea(),c0.GetVolumn();Console.WriteLine(c1s serfacear
113、ea=0, volumn=1,c1.GetArea(),c1.GetVolumn();Console.WriteLine(c2s serfacearea=0, volumn=1,c2.GetArea(),c2.GetVolumn(); 密封类密封类不允许派生子类。密封类不允许派生子类。C#提供一种不能被继承的类,称为密封类。密封类的声明方法是在类名前加上sealed修饰符。修饰符abstract和sealed不能同时使用。下面的代码建立了一个密封类Runtime。public sealed class Runtime private Runtime();/ 私有构造不允许其他代码建立类实例 p
114、ublic static string GetCommandLine()/ 静态方法成员 / 实现代码 public class anotherclass:Runtime /错误,不能继承密封类 /实现代码 密封方法还可以在重写基类中的虚方法或虚属性上使用 sealed 修饰符。这将使您能够允许类从您的类继承,并防止它们重写特定的虚方法或虚属性。在下面的示例中,C从B继承,但C无法重写在A中声明并在B中密封的虚函数F。class A public virtual void F() Console.WriteLine(A.F); public virtual void F2() Console.
115、WriteLine(A.F2); class B : A public sealed override void F() Console.WriteLine(B.F); public override void F2() Console.WriteLine(A.F3); class C : B / Attempting to override F causes compiler error CS0239. / protected override void F() Console.WriteLine(C.F); / Overriding F2 is allowed. public overri
116、de void F2() Console.WriteLine(C.F2); 类嵌套类嵌套内层类被看成是外层类的一个成员。内层类的方法可以访问外层类的私有成员。类外当需要访问内层类,可以使用“.”符号。内层类使用private关键字修饰,就相当于外层类的私有成员,不能在外层类之外被访问到。publicclassAnimalprivatestringstr=mynameisanimal;/私有成员私有成员publicclassHorse/嵌套类嵌套类publicvoidRun()Animala=newAnimal();Console.WriteLine(a.str);/访问外层类私有成员访问外层类
117、私有成员Console.WriteLine(Horserunveryfast);当需要在Animal类之外访问内层类,则使用下面的语句:Animal.Horsehs=newAnimal.Horse();hs.Run();private class Horse例3-15:下面的代码建立一个类distance,代表平面上任意两点间的距离。该类包含两个成员(点p1、p2),每个成员都是内嵌类point的对象。另外,还包含一个构造函数和一个求两点间距离的方法。public class distance /定义一个距离类public class point /定义一个内嵌类 public int x;
118、public int y; public point() Console.Write(x=); x =Convert.ToInt32( Console.ReadLine(); Console.Write(y=); y =Convert.ToInt32( Console.ReadLine(); public point p1, p2; public distance(point p11,point p22) /外层类构造 p1 = p11; p2 = p22;public double get_dis() return Math.Sqrt (Math.Pow(p2.x - p1.x),2)+ M
119、ath.Pow(p2.y - p1.y) ,2);在在Main()方法中运行下面的程序代码:方法中运行下面的程序代码:distancedis;Console.WriteLine(请输入请输入p1、p2两点的坐标:两点的坐标:);dis=newdistance(newdistance.point(),newdistance.point();Console.WriteLine(p1、p2两点间距离为:两点间距离为:+dis.get_dis();3.6 抽象类与接口3.6.1抽象类抽象类类中的方法不提供具体实现,但该类的派生类必须实现类中的方法不提供具体实现,但该类的派生类必须实现这些方法,这些方法
120、在这些方法,这些方法在C#中称为抽象方法。中称为抽象方法。抽象方法必须是一个没有被实现的空方法。包含抽象方抽象方法必须是一个没有被实现的空方法。包含抽象方法的类称为抽象类,抽象类中也可以包含非抽象方法。法的类称为抽象类,抽象类中也可以包含非抽象方法。因为抽象类是用来作为基类的,所以不能直接被外部程因为抽象类是用来作为基类的,所以不能直接被外部程序实例化,而且也不能被密封。序实例化,而且也不能被密封。抽象类抽象类通过关键字通过关键字abstract进行标记将类声明为抽象。进行标记将类声明为抽象。不能创建抽象类的对象,但可以创建抽象类的引用。不能创建抽象类的对象,但可以创建抽象类的引用。一个一个a
121、bstract类可以不包含抽象方法,可以包含非抽象方法和变量。类可以不包含抽象方法,可以包含非抽象方法和变量。抽象方法是虚方法的特例。抽象方法是虚方法的特例。构造函数和静态方法不能是抽象的。构造函数和静态方法不能是抽象的。一个非一个非abstract类不能包含抽象方法。类不能包含抽象方法。子类若要覆盖抽象类的抽象方法时,要使用子类若要覆盖抽象类的抽象方法时,要使用override关键字。关键字。abstractclassWashingMachinepublicWashingMachine()/构造函数构造函数Console.WriteLine(hereisWashingMachine);abs
122、tractpublicvoidWash();/抽象方法抽象方法abstractpublicvoidRinse(intloadSize);/抽象方法抽象方法abstractpubliclongSpin(intspeed);/抽象方法抽象方法WashingMachinem=newWashingMachine();抽象方法的定义抽象方法的定义对于上面的抽象类WashingMachine,派生类中的抽象方法可以如下实现:class MyWashingMachine : WashingMachine public MyWashingMachine() Console.WriteLine(here is
123、MyWashingMachine ); override public void Wash() Console.WriteLine(Wash); override public void Rinse(int loadSize) Console.WriteLine(Rinse); override public long Spin(int speed) Console.WriteLine(Spin); return (speed*1000);当一个类从抽象类派生时,该派生类必须实际提供所有抽象成员的实现,否则,当一个类从抽象类派生时,该派生类必须实际提供所有抽象成员的实现,否则,该派生类仍然是抽
124、象类。如下面的示例所示:该派生类仍然是抽象类。如下面的示例所示:abstractpublicClassApublicabstractvoidF();/抽象方法抽象方法abstractpublicClassB:ApublicvoidG();/附加方法附加方法publicClassC:BpublicoverridevoidF()/抽象方法实现抽象方法实现接口的语法结构:接口的语法结构:访问修饰符访问修饰符interface接口标识符接口标识符:基接口列表基接口列表接口体;接口体;接口成员访问权限为接口成员访问权限为public,但,但不能加访问修饰符不能加访问修饰符接口成员不能有定义接口成员不能有
125、定义接口的成员必须是接口的成员必须是方法,属性,事件或索引器,方法,属性,事件或索引器,不能包含常数、字段、运算符、不能包含常数、字段、运算符、实例构造函数、析构函数或类型。实例构造函数、析构函数或类型。例:例:interfaceIAvoidf();错误错误interfaceIApublicvoidf();错误错误interfaceIAvoidf()接口interface IControl void Paint();/方法成员 int widthget;set;/属性成员interface ITextBox: Icontrol void SetText(string text);interfa
126、ce IListBox: Icontrol void SetItems(string items);Interface IComboBox:ITextBox,IListBox 接口实现接口实现实现:类要继承某个接口用实现:类要继承某个接口用“:”,在类的定义中给出接口中所定义方法,在类的定义中给出接口中所定义方法的实际实现。的实际实现。除显示实现接口外,类中接口实现必须显示声明为除显示实现接口外,类中接口实现必须显示声明为public。public interface Interface1 void fun1(int i); /基成员 public interface Interface2 n
127、ew void fun1(int i);/隐藏基成员 void M1(int y);/添加新成员M1 public class cls1:Interface1 public void fun1(int i). /实现接口方法 public class cls2:Interface2 public void fun1(int i). public void M1(int i). 对接口成员的访问对接口成员的访问对接口方法的调用与类中的情况相同。如果底对接口方法的调用与类中的情况相同。如果底层成员的命名与继承而来的高层成员一致,那层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成
128、员。么底层成员将覆盖同名的高层成员。但由于接口支持多继承,在多继承中,如果两但由于接口支持多继承,在多继承中,如果两个父接口含有同名的成员,这就产生了二义性,个父接口含有同名的成员,这就产生了二义性,这时需要进行显式的声明。这时需要进行显式的声明。显式实现接口显式实现接口假设类实现了两个接口,而这两个接口都有一个假设类实现了两个接口,而这两个接口都有一个名为名为read的方法声明,在类中该如何实现的方法声明,在类中该如何实现read方法方法?例例317显示实现接口显示实现接口publicinterfaceIconnectvoidread();voidwrite();publicinterfac
129、eIbookvoidread();publicclassmyclass:Ibook,Iconnectpublicvoidread()/隐式实现隐式实现Iconnect的的read()Console.WriteLine(实现实现Iconnect.read()方法方法);voidIbook.read()/显式实现显式实现Ibook的的read()Console.WriteLine(实现实现Ibook.read()方法方法);publicvoidwrite()/实现接口方法实现接口方法Console.WriteLine(实现实现write()方法方法);不能加任何访不能加任何访问修饰符问修饰符在在m
130、ain()函数中函数中/隐式实现的隐式实现的Iconnect的的read()方法方法myclasscls=newmyclass();cls.read();/要想显式使用方法,惟一的方法是将对象先转换为接口类型要想显式使用方法,惟一的方法是将对象先转换为接口类型Ibookibk=clsasIbook;if(ibk!=null)ibk.read();运行结果:运行结果:实现实现Iconnect.read()方法方法实现实现Ibook.read()方法方法接口使用接口使用接口由类实现后,接口成员可以通过对象实例访问,就好接口由类实现后,接口成员可以通过对象实例访问,就好像是类的成员一样。像是类的成员
131、一样。接口与对象接口与对象:(1).接口不是类,所以不能用接口创建对象,即不能用接口不是类,所以不能用接口创建对象,即不能用new运算符。运算符。x=newComparable();/错误错误(2).可以声明接口类型的引用,该引用只能指向实现了该可以声明接口类型的引用,该引用只能指向实现了该接口的对象。接口的对象。classStudent:Comparable.Comparablex=newStudent();public interface IA void f();class MyClass : IA public void f() Console.WriteLine(aaa); publi
132、c void f1() Console.WriteLine(bbb); class MyApp static void Main() IA obj = new MyClass(); obj.f(); obj.f1(); 错误错误接口引用只能调用实现的接口成员接口引用只能调用实现的接口成员3 接口的作用如老师和学员都可以收作业,如老师和学员都可以收作业,那么收作业的方法应该放在哪个类?那么收作业的方法应该放在哪个类?A:Teacher类类B:Student类类C:两个都放两个都放D:Person类类E:重新定义重新定义造成代码冗余造成代码冗余如果增加一个工程师类,他不会收作业如果增加一个工程师类
133、,他不会收作业如果继承这个类,如果继承这个类,Person类怎么办类怎么办?调用收作业的方法不调用收作业的方法不需要改变需要改变自定义一个接口来实现自定义一个接口来实现IHomeworkCollectorpublicinterfaceIHomeworkCollectorvoidCollectHomework();publicclassStudent:Person,IHomeworkCollectorclassStudent:Person,IHomeworkCollector.publicvoidCollectHomework()MessageBox.Show(报告老师!作业收集完毕!报告老师!
134、作业收集完毕!);classTeacher:Person,IHomeworkCollectorpublicvoidCollectHomework()MessageBox.Show(“同学们,请交作业!同学们,请交作业!);1、定义一个收作业的接口、定义一个收作业的接口2、在有收作业功能的类中实现该接口、在有收作业功能的类中实现该接口3、不同的类收作业方式的不同、不同的类收作业方式的不同1、接口作为参数使用、接口作为参数使用privatevoidDoCollectHomework(IHomeworkCollectorcollector)collector.CollectHomework();无论
135、谁收作业无论谁收作业这里都不这里都不需要做任何改变需要做任何改变2、接口作为返回值使用、接口作为返回值使用scofield=newStudent();DoCollectHomework(scofield);privateIHomeworkCollectorCreateHomeworkCollector(stringtype)switch(type)casestudent:collector=newStudent(Scofield,Genders.Male,28,越狱狱越狱狱);break;returncollector返回一个实现该返回一个实现该接口的对象接口的对象IHomeworkColle
136、ctor collector=CreateHomeworkCollector(“student”);collector.CollectHomework();作为返回值和参数的意义作为返回值和参数的意义接口作为参数接口作为参数传递给它的值为实现该接口的对象传递给它的值为实现该接口的对象 接口作为返回值接口作为返回值 返回一个实现了该接口的对象返回一个实现了该接口的对象例例3-163-16使用接口技术实现不同对象的面积求和使用接口技术实现不同对象的面积求和usingSystem;publicinterfaceICalAreaAndVolumn/声明接口声明接口doubleGetArea();pub
137、licclassSphere:ICalAreaAndVolumn/球类球类privatedoubleradius;publicSphere(doubler)radius=r;publicdoubleGetArea()return(4*Math.PI*radius*radius);publicclassCylinder:ICalAreaAndVolumn/圆柱类圆柱类privatedoubleradius,height;publicCylinder(doubler,doubleh)radius=r;height=h;publicdoubleGetArea()return(2*Math.PI*ra
138、dius*radius+2*Math.PI*radius*height);publicclassCone:ICalAreaAndVolumn/圆锥类圆锥类privatedoubleradius,height;publicCone(doubler,doubleh)radius=r;height=h;publicdoubleGetArea()return(Math.PI*radius*(radius+Math.Sqrt(height*height+radius*radius);publicclassMyApppublicstaticdoubleSumAreas(ICalAreaAndVolumna
139、rray)doubletot=0.0;for(inti=0;iarray.Length;i+)tot+=arrayi.GetArea();returntot;publicstaticvoidMain()Spheresp=newSphere(2);Cylindercd=newCylinder(2,10);Conecn=newCone(2,20);ICalAreaAndVolumnarray=sp,cd,cn;Console.WriteLine(totalarears=0,SumAreas(array);is运算符运算符is运算符可以检查对象与类之间的关系,形式为:运算符可以检查对象与类之间的关系
140、,形式为:if(objisclassname)当当obj为为classname类或其子类的对象时,运算返回类或其子类的对象时,运算返回true。如果引用没有指向对象,编译时报错。如果引用没有指向对象,编译时报错。可用于确定接口是否可用可用于确定接口是否可用Sphereobj=newSphere(1);/如果如果Sphere实现了实现了ICalAreaAndVolumn接口接口if(objisICalAreaAndVolumn).using System;class Class1class Class2class IsTest static void Test(object o) Class1
141、a; Class2 b; if (o is Class1) Console.WriteLine(o is Class1); else if (o is Class2) Console.WriteLine(o is Class2); else Console.WriteLine(o is neither Class1 nor Class2.); static void Main() Class1 c1 = new Class1(); Class2 c2 = new Class2(); Test(c1); Test(c2); Test(a string); oisClass1oisClass2oi
142、sneitherClass1norClass2.as运算符运算符as运算符完成的功能等价于:先用运算符完成的功能等价于:先用is检查,检查,再执再执行对象类型转换。行对象类型转换。如果类型不兼容,如果类型不兼容,as运算返回运算返回null。Sphereobj=newSphere(1);ICalAreaAndVolumnmyICal;myICal=objasICalAreaAndVolumn;/如果如果Sphere实现了实现了ICalAreaAndVolumn接口接口if(myICal!=null).using System;class Class1 class Class2 class Ma
143、inClass static void Main() object objArray = new object6; objArray0 = new Class1(); objArray1 = new Class2(); objArray2 = hello; objArray3 = 123; objArray4 = 123.4; objArray5 = null; for (int i = 0; i objArray.Length; +i) string s = objArrayi as string; Console.Write(0:, i); if (s != null) Console.W
144、riteLine( + s + ); else Console.WriteLine(not a string); 0:notastring1:notastring2:hello3:notastring4:notastring5:notastring接口和抽象类的对比接口和抽象类的对比抽象类抽象类接口接口不不同同点点用用abstract定义定义用用interface定义定义只能继承一个类只能继承一个类可以实现多个接口可以实现多个接口非抽象派生类必须实现抽象方法非抽象派生类必须实现抽象方法实现接口的类必须实现实现接口的类必须实现所有成员所有成员需要需要override实现抽象方法实现抽象方法直接实
145、现直接实现相相同同点点不能实例化不能实例化包含未实现的方法包含未实现的方法派生类必须实现未实现的方法派生类必须实现未实现的方法结构结构结构是一种用结构是一种用struct声明的自定义数据类型。它和类相似,声明的自定义数据类型。它和类相似,可以包含构造函数,字段,属性,方法等。可以包含构造函数,字段,属性,方法等。一般情况下结构中只是一些数据,要是需要定义方法,一一般情况下结构中只是一些数据,要是需要定义方法,一般将它定义为类。般将它定义为类。结构不支持继承,但可继承接口。结构不支持继承,但可继承接口。访问修饰字访问修饰字struct结构名结构名:接口接口结构体结构体下面的结构包含三个成员:下面
146、的结构包含三个成员:structSimpleStructprivateintxval;/私有字段私有字段publicintX/属性属性getreturnxval;setif(value100)xval=value;publicvoidDisplayX()/方法方法Console.WriteLine(Thestoredvalueis:0,xval);例例318publicstructPointpublicintx,y;publicPoint(intx,inty)/构造函数必须带参数,且必须对字段进行赋值构造函数必须带参数,且必须对字段进行赋值this.x=x;this.y=y;publicvoi
147、ddraw()Console.WriteLine(结构对象创建之后才能调用结构对象创建之后才能调用);classMainClasspublicstaticvoidMain()Pointpt1;/不用不用new建立结构对象建立结构对象pt1.x=10;/初始化结构对象,才能使用,否则出错初始化结构对象,才能使用,否则出错pt1.y=20;Pointpt2=newPoint(20,20);/用用new建立结构对象建立结构对象Pointpt3=newPoint();/调用了系统提供的默认构造函数调用了系统提供的默认构造函数/打印显示打印显示Console.WriteLine(pt1:);Consol
148、e.WriteLine(x=0,y=1,pt1.x,pt1.y);Console.WriteLine(pt2:);Console.WriteLine(x=0,y=1,pt2.x,pt2.y);对于结构的使用需要注意以下几点:1.结构不能包含显式的无参数构造函数。2. 显式定义的构造函数必须带参数。3.对于结构中的实例字段成员,不能在声明时赋值初始化。4.在声明了结构类型后,可以使用new运算符创建结构对象。如果不使用new,那么在初始化所有字段前,字段保持未赋值状态且对象不可用。5.结构是值类型,类是引用型。6.结构不支持继承,但可继承接口。以下任何一条,就应该使用类:1.需要派生其他类型。2
149、.需要继承。3.该类型作为方法参数传递。因为结构是值类 型,每次调用都要创建结构的副本。但结构放在数组中例外。4. 该类型用作方法的返回类型。3.7委托与事件委托与事件委托是一种可以指向方法的委托是一种可以指向方法的引用,可以理解为一种引用,可以理解为一种函数函数指针指针,是类型安全的。它类,是类型安全的。它类似于似于C+中的函数指针,通中的函数指针,通过对于方法特征和返回值类过对于方法特征和返回值类型的声明,封装了具有相同型的声明,封装了具有相同特征和返回类型的方法。特征和返回类型的方法。使用委托需要三个步骤:使用委托需要三个步骤:声明委托类型声明委托类型创建委托实例创建委托实例向委托实例注
150、册方法向委托实例注册方法委托Multiply(int,int).Divide(int,int).在运行时确定调用哪种方法委托和方法必须具有相同的签名-public delegate Call(int n1, int n2);-class Delegates/ 委托定义public delegate int Call(int n1, int n2);class Math/ 乘法方法public int Multiply(int n1, int n2)return n1*n2; / 除法方法public int Divide(int n1, int n2) if(n2!=0)return n1/n
151、2;static void Main(string args)/ 委托的对象Call objCall;/ Math 类的对象Math objMath = new Math();/ 将方法与委托关联起来objCall = new Call(objMath.Multiply);/ 将委托实例化result = objCall(4, 3);System.Console.WriteLine(结果为 0, result); 将方法与委托关联起来事件事件抢答者宣布人宣布人抢答者“请听题”集中注意力聆听其他人事件源事件的发布者事件的订阅人未订阅该事件定义事件为对象订阅该事件 将发生的事件通知给订阅人定义事件
152、定义事件访问修饰符 event 委托名 事件名; 语法public delegate void delegateMe();private event delegateMe eventMe;事件订阅对象事件订阅对象eventMe += new delegateMe(objA.Method);eventMe += new delegateMe(objB.Method);去掉事件去掉事件eventMe -= new delegateMe(objA.Method);eventMe -= new delegateMe(objB.Method);通知订阅对象通知订阅对象if(condition) even
153、tMe();调用订阅特定事件的对象的所有委托示例示例class ClassApublic void DispMethod()Console.WriteLine(“Class A 已接到 NotifyEveryOne 事件的通知!); / 第二个类class ClassBpublic void DispMethod()Console.WriteLine(“Class B 已接到 NotifyEveryOne 事件的通知! );示例示例class Delegate/ 定义委托public delegate void MeDelegate();/ 定义事件public event MeDelegat
154、e NotifyEveryOne;public void Notify()/ 如果事件不为 nullif(NotifyEveryOne != null)Console.WriteLine(触发事件:);/ 触发事件NotifyEveryOne(); 示例示例class TestEventsSTAThreadstatic void Main(string args) / 委托的对象 Delegate objDelegate = new Delegate(); / ClassA 的对象 ClassA objClassA = new ClassA(); / ClassB 的对象 ClassB obj
155、ClassB = new ClassB(); / 订阅该事件 objDelegate.NotifyEveryOne += new Delegate.MeDelegate(objClassA.DispMethod); objDelegate.NotifyEveryOne += new Delegate.MeDelegate(objClassB.DispMethod); objDelegate.Notify();ZJWCHC第第4章章C#高级编程高级编程调试调试应用程序开发可以安装在客户端机器上应用程序必须无错误无故障 可靠 稳健查找和排除查找和排除错误或故障称为错误或故障称为调试调试调试的必要性
156、调试的必要性在事物处理过程中,系统显示错误消息在事物处理过程中,系统显示错误消息系统发生故障系统发生故障必须重新输入全部信息在部署应用程序前必须先对其进行调试在部署应用程序前必须先对其进行调试错误类型错误类型错误类型语法错误逻辑错误运行时错误语法错误、缺少括号等在编译时确定易于确定错误的算法导致错误结果、公式错误等 在执行过程中确定难以调试内存泄漏、以零作除数、异常在运行时确定难以调试调试过程调试过程调试器观察程序的运行时行为 跟踪变量的值确定语义错误的位置查看寄存器的内容查看内存空间 调试过程调试过程暂停暂停可在代码中插入“断点”,以便在特定行处暂停执行该代码调试过程调试过程右键单击所需代码
157、行,以设置断点选择“插入断点”调试过程调试过程选择“调试” “继续”以便继续执行程序调试过程调试过程.NET 集成开发环境Debug模式Release模式VS.NET中的调试工具中的调试工具“局部变量”窗口VS.NET中的调试工具中的调试工具“监视”窗口VS.NET的调试工具的调试工具“快速监视”对话框VS.NET中的调试工具中的调试工具“即时”窗口VS.NET中的调试工具中的调试工具跨语言调试 调试使用 .NET 框架编写的应用程序以及 Win32 本机应用程序加入正在运行的程序调试多个程序Visual Studio .NET 调试器的功能异常异常帐户姓名 余额300123小王小王30012
158、4小黄小黄7000311320小李小李网上银行网上银行某学生小王转帐5000到其朋友小李的帐面上04500数据库系统将查询发送到数据库中系统将查询发送到数据库中tranfer_money() sendquery(); . . 余额 4500-5000程序崩溃程序崩溃拒绝交易拒绝交易错误错误 系统出现故障系统出现故障 “C#”中的异常 C#中的异常处理中的异常处理.INPUT DivisorIF Divisor = 0 THENResult = Divident/Divisor.代码片段 1输入除数结果 =_0 24GOTO PREVIOUS LINE触发异常处理程序C#中的异常处理中的异常处理
159、.INPUT DivisorResult = Divident/Divisor.代码片段 1“用户自定义”错误检查机制难以检查输入的任何难以检查输入的任何“特殊字符特殊字符”IF Divisor = 0 THEN GOTO PREVIOUS LINEIF Divisor 0 THEN PRINT “无效输入”运行库运行库运行库应当提供“错误检查机制” 错误与异常错误与异常错误:错误:可预见,如信用卡号格式不对或口令不可预见,如信用卡号格式不对或口令不对。可由程序代码进行排除。对。可由程序代码进行排除。异常:异常:与程序无关的外部原因造成。如数据表与程序无关的外部原因造成。如数据表不可用或硬件故
160、障等。不可用或硬件故障等。System.ExceptionSystem.Exception属性Message获取描述当前异常的消息。获取描述当前异常的消息。Source获获取取或或设设置置导导致致错错误误的的应应用用程程序序或或对对象象的的名名称称(程程序序集集的名称的名称)。TargetSite获取引发当前异常的方法。获取引发当前异常的方法。StackTrace获获取取当当前前异异常常发发生生时时调调用用堆堆栈栈上上的的帧帧的的字字符符串串表表示示形式。形式。System.Exception在 C# 程序中,引发异常共有以下两种方式使用显式 throw 语句来引发异常。在此情况下,控制权将无
161、条件转到处理异常的部分代码使用语句或表达式在执行过程中激发了某个异常的条件,使得操作无法正常结束,从而引发异常Try.Catch.Finallytry和和catch块块滤水器滤水器filter_water() try water(); catch impurities.Show(); . .过滤水杂质/程序代码 /错误处理代码 try/程序代码catch (IOException E)/错误处理代码try和和catch块块try/程序代码catch (IOException E)/错误处理代码引发I/O 设备异常try和和catch块块try/程序代码catch( E)/错误处理代码可处理系统
162、中的任何一种异常System.Exceptiontry和和catch块块if (grade 150)throw new InvalidNumberInput(grade+ “不是合法的成绩”);throw 可用来引发自定义异常“InvalidNumberInput” 使用使用finallytry/程序代码catch/错误处理代码finally/finally 代码无论有否异常该代码都会执行多重多重catch块块try/程序代码catch (IOException E)/错误处理代码catch (OutOfMemoryException E)/错误处理代码用于捕捉两种异常的“catch”块usi
163、ngSystem;publicclassTestExceppublicstaticintCalc(intj)return100/j;classMyApppublicstaticvoidMain()TestExcepexTest=newTestExcep();tryintdZero=TestExcep.Calc(0);Console.WriteLine(Result:0,dZero);catch(DivideByZeroExceptionex)Console.WriteLine(ex.Message:0,ex.Message);Console.WriteLine(ex.Source:0,ex.S
164、ource);Console.WriteLine(ex.TargetSite:0,ex.TargetSite.ToString();Console.WriteLine(ex.StackTrace:0,ex.StackTrace);catch(Exceptionex)Console.WriteLine(General+ex.Message);finallyConsole.WriteLine(Cleanupoccurshere);ex.Message:试图除以零。试图除以零。ex.Source:005ex.TargetSite:Int32Calc(Int32)ex.StackTrace:在在Tes
165、tExcep.Calc(Int32j)位置位置E:我的桌面临时文件夹我的桌面临时文件夹实验编程实验编程CSharp005Program.cs:行号行号96在在MyApp.Main()位置位置E:我的桌面临时文件夹我的桌面临时文件夹实验编程实验编程CSharp005Program.cs:行号行号107Cleanupoccurshere请按任意键继续请按任意键继续.如何创建定制异常类如何创建定制异常类usingSystem;publicclassNoDescException:ApplicationExceptionpublicNoDescException()publicNoDescExcept
166、ion(stringmessage):base(message)publicNoDescException(stringmessage,ExceptioninnerEx):base(message,innerEx)publicinterfaceIFun1stringShowMe();publicinterfaceIFun2stringShowMe();classCircle:IFun1publicstringShowMe()returnCircle-IFun1;publicclassObjShowMepublicstaticvoidShowMe(objectobj)if(!(objisIFun
167、1&objisIFun2)thrownewNoDescException(Interfacenotimplementedfor+obj.ToString();publicclassMyAppstaticvoidMain()CirclemyCir=newCircle();tryObjShowMe.ShowMe(myCir);catch(NoDescExceptionex)Console.WriteLine(ex.Message);未处理异常未处理异常当当CLR找不到处理异常的找不到处理异常的catch过滤器时过滤器时usingSystem;classMyApppublicstaticvoidMa
168、in()tryintdZero=1/0;finallyConsole.WriteLine(“finally);定制处理未处理异常定制处理未处理异常终止应用程序之前记录有关异常的信息。如果有足够的终止应用程序之前记录有关异常的信息。如果有足够的有关应用程序状态的信息,则可以采取其他措施,如保有关应用程序状态的信息,则可以采取其他措施,如保存程序数据以便于以后进行恢复。存程序数据以便于以后进行恢复。建议谨慎行事,因为未处理异常时可能会损坏程序数据。建议谨慎行事,因为未处理异常时可能会损坏程序数据。没有通用的方法适用于所有没有通用的方法适用于所有C#程序。程序。Windows窗体应用:窗体应用:Ap
169、plicatioin.ThreadException+=newThreadExceptionEventHandler(method);Windows控制台应用:控制台应用:Thread.GetDomain().UnhandledException+=newUnhandledExceptionEventHandler(method);usingSystem;publicclassTestExceppublicstaticintCalc(intj)return100/j;publicclassUnForgivenpublicstaticvoidMyUnhandleMethod(objectsend
170、er,UnhandledExceptionEventArgse)#ifDEBUGConsole.WriteLine(Debug:+e.ToString();#elseConsole.WriteLine(Release:+e.ToString();#endifclassMyApppublicstaticvoidMain()Thread.GetDomain().UnhandledException+=newUnhandledExceptionEventHandler(UnForgiven.MyUnhandleMethod);tryintdZero=TestExcep.Calc(0);finally
171、Console.WriteLine(a);s定制类中实现定制类中实现System.Object方法方法ToString():默认情况下,返回类名。应覆盖默认情况下,返回类名。应覆盖此方法,显示出对象与访类其他实例不同的特此方法,显示出对象与访类其他实例不同的特有内容。有内容。Equals():定制类需定义定制类需定义“相等相等”的含义:可的含义:可能两个对象有相同的字段值变相等,也可能引能两个对象有相同的字段值变相等,也可能引用了相同的内存地址才相等。用了相同的内存地址才相等。定制定制ToString()默认返回默认返回.定制定制ToString方法实例:方法实例:usingSystem.Te
172、xt;usingSystem;publicclassChairprivatedoublemyPrice;privatestringmyVendor,myID;publicChair(doubleprice,stringvendor,stringsku)myPrice=price;myVendor=vendor;myID=sku;publicoverridestringToString()StringBuilderchairSB=newStringBuilder();chairSB.AppendFormat(ITEM=Chair);chairSB.AppendFormat(tVENDOR=0,m
173、yVendor);chairSB.AppendFormat(tPRICE=0,myPrice.ToString();returnchairSB.ToString();staticvoidMain()ChairmyChair=newChair(120.0,Broyhill,60-1222);Console.WriteLine(myChair.ToString();定制定制Equals()比较两个引用类型的对象时,当它们指向相同比较两个引用类型的对象时,当它们指向相同的对象,返回的对象,返回true。如果基于值来比较对象时,必须覆盖该方法。如果基于值来比较对象时,必须覆盖该方法。String类就是
174、这样一个例子,其虽然是引用类类就是这样一个例子,其虽然是引用类型,但它会基于字符串中的字符串完成比较。型,但它会基于字符串中的字符串完成比较。usingSystem;publicclassChairprivatedoublemyPrice;privatestringmyVendor,myID;publicChair(doubleprice,stringvendor,stringsku)myPrice=price;myVendor=vendor;myID=sku;publicoverrideboolEquals(objectobj)if(obj=null)returnfalse;if(this.
175、GetType()!=obj.GetType()returnfalse;ChairotherObj=(Chair)obj;if(!myVendor.Equals(otherObj.myVendor)returnfalse;if(!myPrice.Equals(otherObj.myPrice)returnfalse;if(!myID.Equals(otherObj.myID)returnfalse;returntrue;publicoverrideintGetHashCode()returnmyID.GetHashCode();staticvoidMain()ChairmyChair=newC
176、hair(120.0,Broyhill,60-1222);ChairnewChair=newChair(120.0,Broyhill,60-1222);booleq=myChair.Equals(newChair);Console.WriteLine(eq.ToString();覆盖覆盖GetHashCode()GetHashCode方法为对象生成一个方法为对象生成一个Int32类型的散列码。类型的散列码。.NET要求两个相同的对象必须要求两个相同的对象必须有相同的散列码,不同的对象不保证有不同的有相同的散列码,不同的对象不保证有不同的散列码。散列码。Equals方法必须和方法必须和GetHa
177、shCode方法成对方法成对出现。出现。克隆来创建对象副本克隆来创建对象副本Object中的中的MemberwiseClone():默认返默认返回对象的一个副本,是一种浅拷贝。回对象的一个副本,是一种浅拷贝。可以实现自已的克隆方法进行深拷贝。可以实现自已的克隆方法进行深拷贝。不能克隆基本类型。可克隆的类必须实现不能克隆基本类型。可克隆的类必须实现ICloneable接口。接口。publicinterfaceICloneableObjectClone();using System;public class Chair : ICloneable private double myPrice; pr
178、ivate string myVendor, myID; public Upholstery myUpolstery; public Chair(double price, string vendor, string sku) myPrice = price; myVendor = vendor; myID = sku; public Object Clone() return MemberwiseClone(); public class Upholstery public string fabric; public Upholstery(string fab) fabric = fab;
179、class MyApp static void Main() Chair myChair = new Chair(120.0, Broyhill, 60-1222); Chair chairClone = (Chair)myChair.Clone(); bool isEqual; isEqual = Object.ReferenceEquals(myChair, chairClone); Console.WriteLine(isEqual.ToString(); isEqual = Object.ReferenceEquals(myChair.myUpolstery, chairClone.m
180、yUpolstery); Console.WriteLine(isEqual.ToString(); 什么是序列化什么是序列化Profile对象对象界面语言界面语言:英语英语RssFeed对象对象存储存储介质介质存储存储序列化是将对象的状态存储到特定存储介质中的过程序列化是将对象的状态存储到特定存储介质中的过程代理服务器代理服务器特性特性SerializableabstractclassFeedBase标识这个类是可标识这个类是可序列化的序列化的可序列化就是这个类的一个可序列化就是这个类的一个特性特性描述性关键字描述性关键字对程序中的元素如:类、字段、方法、属性对程序中的元素如:类、字段、方法
181、、属性命名时以命名时以Attribute结尾结尾:SerializableAttribute使用时省略使用时省略AttributepublicsealedclassSerializableAttribute特性其实是特性其实是一个类一个类可在类成员附加可在类成员附加NonSerialized属性,将其排除在属性,将其排除在串行化范围之外。串行化范围之外。publicclassChairNonSerializedpublicdoublemyPrice;publicstringmyVendor,myID;publicChair()publicChair(doubleprice,stringvend
182、or,stringsku)myPrice=price;myVendor=vendor;myID=sku;使用序列化使用序列化fileStream=newFileStream(profile.bin,FileMode.Create);BinaryFormatterbf=newBinaryFormatter();bf.Serialize(fileStream,Profile);SerializableabstractclassFeedBase要存储的对象标记为可序列化,包括他的父类和属性的要存储的对象标记为可序列化,包括他的父类和属性的类类使用二进制方式存储对象使用二进制方式存储对象二进制格式化器
183、二进制格式化器将对象以二进制方将对象以二进制方式格式化为流式格式化为流Serialize(StreamserializationStream,Objectgraph)流流对象对象Serialize的用法的用法:序列化的过程序列化的过程格式化程序格式化程序对象可否序列化对象可否序列化子类成员子类成员可否序列化可否序列化将对象格式化将对象格式化写入存储介质写入存储介质异常退出异常退出序列化对象中的序列化对象中的子类成员子类成员YYNN反序列化反序列化把把Profile对象存储成文件,怎么取出来呢?对象存储成文件,怎么取出来呢?读取读取反序列化则是从特定存储介质中的数据重新构建对象的过程反序列化则是
184、从特定存储介质中的数据重新构建对象的过程存储存储介质介质Profile对象对象界面语言界面语言:英语英语RssFeed对象对象代理服务器代理服务器数据转换为对象数据转换为对象使用反序列化使用反序列化将序列化好的将序列化好的Profile数据反序列化为对象数据反序列化为对象fileStream=newFileStream(profile.bin,FileMode.Open);BinaryFormatterbf=newBinaryFormatter();Profile=(Profile)bf.Deserialize(fileStream);将指定流反序列化将指定流反序列化类型转换类型转换publi
185、cObjectDeserialize(StreamserializationStream)Deserialize的用法的用法:流流对象对象需要类型转换需要类型转换using System;using System.Runtime.Serialization.Formatters.Binary;using System.IO;Serializablepublic class Chair public double myPrice; public string myVendor, myID; public Chair() public Chair(double price, string vend
186、or, string sku) myPrice = price; myVendor = vendor; myID = sku; class MyApp static void Main() Chair myChair = new Chair(100.0, Broyhill, 10-09); FileStream fs = new FileStream(C:chairs.dat, FileMode.Create); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, myChair); fs.Close(); Chair ne
187、wChair = new Chair(); fs = new FileStream(C:chairs.dat, FileMode.Open); newChair = (Chair)bf.Deserialize(fs); Console.WriteLine(newChair.myPrice.ToString() + + newChair.myVendor + + newChair.myID); 串行化事件串行化事件事件事件属性属性OnSerializingOnSerializingOnSerializedOnSerializedOnDeSerializingOnDesializingOnDeSe
188、rializedOnDeSerialized这些事件处理程序在被串行化的对象中实现,必须满足以这些事件处理程序在被串行化的对象中实现,必须满足以下两个要求:下两个要求:必须为方法附加与事件相关的属性必须为方法附加与事件相关的属性方法必须有以下签名:方法必须有以下签名:void(StreamingContextcontext)例如:例如:OnDeSerializedvoidOnMyDeserialized(StringContextcontext)注:需加上注:需加上usingSystem.Runtime.Serialization;处理串行化对象的版本变化处理串行化对象的版本变化如果删除了原对
189、象的一个字段,格式化器只是如果删除了原对象的一个字段,格式化器只是忽略逆串行化流中的多余数据。忽略逆串行化流中的多余数据。Serializablepublic class Chair public double myPrice; public string myVendor, myID; .Serializablepublic class Chair public string myVendor, myID; 如果原对象增加了新字段,格式化器发现新字如果原对象增加了新字段,格式化器发现新字段后,会抛出异常段后,会抛出异常(.NET2.0)。SerializablepublicclassChai
190、rpublicdoublemyPrice;publicstringmyVendor,myID;.SerializablepublicclassChairpublicstringmyVendor,myID;可以为新字段附可以为新字段附加加OptionalField属性。格式器会为属性。格式器会为新字段指定一个默新字段指定一个默认值。认值。SerializablepublicclassChairOptionalFieldpublicdoublemyPrice;publicstringmyVendor,myID;.还可以利用逆串行化事件为新字段赋值。还可以利用逆串行化事件为新字段赋值。OnDeser
191、ializedvoidOnMyDeserialized(StreamingContextcontext)if(myVendor=“Lane”)finish=“OaK”;elsefinish=“Cherry”;反射反射可以可以ILDasm反编译工具浏览一个反编译工具浏览一个dll和和exe的的构成构成这种机制叫做这种机制叫做反射(反射(Reflection)应用程序或应用程序或dll类的属性类的属性类的方法类的方法应用程序信息应用程序信息用于在运行时通过编程方式获得类型信息用于在运行时通过编程方式获得类型信息反射反射现场演示现场演示通过代码演示获取通过代码演示获取dll的版本号的版本号using
192、System.Reflection;classProgramstaticvoidMain(stringargs)stringversion=Assembly.LoadFile(D:MyNewsReader.exe).GetName().Version.ToString();Console.WriteLine(version);引入命名空间引入命名空间反射反射什么是设计模式什么是设计模式模式就是得到很好研究的范例模式就是得到很好研究的范例走为上走为上围魏救赵围魏救赵声东击西声东击西设计模式是软件开发过程中经验的积累设计模式是软件开发过程中经验的积累特定问题的经过实践检验的特定解决方法特定问题的经
193、过实践检验的特定解决方法简单工厂模式简单工厂模式简单工厂模式的原理简单工厂模式的原理父类产品父类产品子类产品子类产品A子类产品子类产品B子类产品子类产品C工厂工厂客户客户简单工厂模式简单工厂模式工厂类:担任这个角色的是工厂方法模式的工厂类:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,厂类在客户端的直接调用下创建产品对象,它往往由一个具体的类实现。它往往由一个具体的类实现。抽象产品角色:担任这个角色的类是由工厂抽象产品角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或她们共同方法模式所创
194、建的对象的父类,或她们共同拥有的接口。一般由接口或抽象类实现。拥有的接口。一般由接口或抽象类实现。具体产品角色:工厂方法模式所创建的任具体产品角色:工厂方法模式所创建的任何对象都是这个角色的实例,由具体类实现。何对象都是这个角色的实例,由具体类实现。简单工厂模式优缺点简单工厂模式优缺点模式的核心是工厂类,这个类负责产品的创模式的核心是工厂类,这个类负责产品的创建,而客户端可以免去产品创建的责任,这建,而客户端可以免去产品创建的责任,这实现了责任的分割。但由于工厂类集中了所实现了责任的分割。但由于工厂类集中了所有产品创建逻辑的,如果不能正常工作的话有产品创建逻辑的,如果不能正常工作的话会对系统造
195、成很大的影响。如果增加新产品会对系统造成很大的影响。如果增加新产品必须修改工厂角色的源码。必须修改工厂角色的源码。设计模式的意义设计模式的意义提高软件的可复用性提高软件的可复用性灵活,适应软件设计的变化灵活,适应软件设计的变化面向对象在实际应用中集中体现面向对象在实际应用中集中体现简单工厂模式实例简单工厂模式实例父类产品父类产品子类产品子类产品A子类产品子类产品C工厂工厂客户客户publicinterfaceIApparelstringShowMe();publicclassSportShirt:IApparelpublicstringShowMe()return(“SportsShirt”)
196、;publicclassDressShirt:IApparelpublicstringShowMe()return(“DressShirt”);publicclassApparelFactorypublicIApparelCreateApparel(stringapptype)switch(apptype)case“DRESSSHIRT”:returnnewDressShirt();case“SPORTSSHIRT”:returnnewSportsShirt();returnnull;ApparelFactory=newApparelFactory();IApparelobj1=factory
197、.CreateApparel(“DRESSSHIRT”);IApparelobj2=factory.CreateApparel(“SPORTSSHIRT”);stringshirtType=obj1.ShowMe();为什么需要抽象工厂设计模式为什么需要抽象工厂设计模式父类产品父类产品子类产品子类产品A子类产品子类产品B子类产品子类产品C工厂工厂客户客户:简单工厂设计模式原理结构:简单工厂设计模式原理结构什么是抽象工厂设计模式什么是抽象工厂设计模式什么是抽象工厂设计模式什么是抽象工厂设计模式抽象工厂抽象工厂实体工厂实体工厂2实体工厂实体工厂1抽象产品抽象产品A抽象产品抽象产品B实体产品实体产品
198、B1实体产品实体产品B2实体产品实体产品A1实体产品实体产品A2客户客户:抽象工厂设计模式原理结构:抽象工厂设计模式原理结构什么是抽象工厂设计模式什么是抽象工厂设计模式抽象工厂角色抽象工厂角色:担任这个角色的是工厂方法模式:担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通的核心,它是与应用系统的商业逻辑无关的。通常使用接口或抽象类实现。常使用接口或抽象类实现。具体工厂角色具体工厂角色:这个角色直接在客户端的调用下这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻对象的逻
199、辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。通常使用具体的类实现。辑紧密相关的。通常使用具体的类实现。抽象产品角色抽象产品角色:担任这个角色的类是抽象工厂方担任这个角色的类是抽象工厂方法模式所创建的对象的父类,或它们共同拥有的法模式所创建的对象的父类,或它们共同拥有的接口。通常使用接口或抽象类实现这一角色。接口。通常使用接口或抽象类实现这一角色。具体产品角色具体产品角色:抽象工厂模式所创建的任何产品抽象工厂模式所创建的任何产品对象都是某一具体产品类的实例。这是客户端最对象都是某一具体产品类的实例。这是客户端最终需要的东西。通常使用具体类实现这个角色。终需要的东西。通常使用具体类实现这个角色
200、。什么是抽象工厂设计模式什么是抽象工厂设计模式1、提供一系列相互依赖对象的创建工作、提供一系列相互依赖对象的创建工作2、封装对象常规的创建方法(、封装对象常规的创建方法(new)3、提供统一调用数据访问方法的方式、提供统一调用数据访问方法的方式4、避免调用数据访问方法和具体对象创建工作的紧耦合、避免调用数据访问方法和具体对象创建工作的紧耦合什么是抽象工厂设计模型什么是抽象工厂设计模型提供一个创建一系列相关或相互依赖对象的接提供一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类口,无需指定它们具体的类客户请求客户请求 抽象工厂抽象工厂抽象产品抽象产品如何用抽象工厂设计模式构建我们的数据
201、访问层?如何用抽象工厂设计模式构建我们的数据访问层?使用抽象工厂模式使用抽象工厂模式一个系统不应当依赖于产品类实例如何被创建、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模组合和表达的细节,这对于所有形态的工厂模式都是重要的。式都是重要的。这个系统的产品有多于一个的产品族,而系统这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。只消费其中某一族的产品。同属于同一个产品族的产品是在一起使用的,同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。这一约束必须在系统的设计中体现出来。系统提供一个产品类的库,所有的产品以同样系统
202、提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。的接口出现,从而使客户端不依赖于实现。如何使用抽象工厂设计模式如何使用抽象工厂设计模式1、用、用抽象工厂抽象工厂生产抽象产品生产抽象产品2、用、用实体工厂实体工厂生产生产实体产品实体产品3、用、用抽象产品抽象产品提供提供实体产品实体产品访问接口访问接口4、用、用实体产品实体产品实现自己的功能实现自己的功能:抽象工厂设计模式中各个象的主要功能、职责:抽象工厂设计模式中各个象的主要功能、职责应用示例应用示例礼服衬衫实体工厂礼服衬衫实体工厂抽象产品抽象产品抽象工厂抽象工厂运动衫实体工厂运动衫实体工厂运动衫运动衫实实体产品体产品
203、礼服衬衫实礼服衬衫实体产品体产品客户客户publicabstractclassAppFactorypublicabstractIApparelCreateApparel();publicclassDressShirtFactory:AppFactorypublicoverrideIApparelCreateApparel()returnnewDressShirt();publicclassSportShirtFactory:AppFactorypublicoverrideIApparelCreateApparel()returnnewSportsShirt();publicclassAppar
204、elCollectorpublicvoidCollectApparel(AppFactoryfactory)IApparelapparel=factory.CreateApparel();AppFactoryfactory=newDressShirtFactory();IApparelobj=newApparelCollector().CollectApparel(factory);ZJWCHC第第5章章集合类及其接口集合类及其接口System.Array简介简介3-2数组定义:数据类型 数组名称;int MyArray = 1,2,3,4,5,6,7;MyArray0, MyArray1,
205、MyArray2MyArray6 MyArray 0 = 604 System.Array简介简介3-3System.ArrayArray是抽象的基类,提供 CreateInstance 方法来创建数组Array obj = Array.CreateInstance(typeof(string),10); Array obj1 = Array.CreateInstance(typeof(string),2,3,4);System.Array的属性和方法的属性和方法属性属性LengthLength方法方法BinarySearchBinarySearchClearClearCopyCopyRank
206、RankIsReadOnlyIsReadOnlyIsFixedSizeIsFixedSizeCopyToCopyToCreateInstanceCreateInstanceGetLengthGetLengthGetLowerBoundGetLowerBoundGetUpperBoundGetUpperBoundGetValueGetValueIndexOfIndexOfLastIndexOfLastIndexOfReverseReverseSetValueSetValueSortSort示例示例2-1static void Main(string args) /构建 objNames 数组 A
207、rray objNames = Array.CreateInstance(typeof(string),5); /初始化值 objNames.SetValue(“A,0); objNames.SetValue(“B,1); objNames.SetValue(“C,2); objNames.SetValue(“D,3); objNames.SetValue(“E,4); Console.WriteLine(“数组值); for(int ctr = 0 ; ctr 5; ctr+) Console.WriteLine(“元素 0: 1,ctr+1,objNames.GetValue(ctr);
208、使用 GetValue() 方法检索数组值使用 SetValue() 方法存储字符串将 objNames 实例化为字符串对象并且其中存放 5 个元素示例示例2-2Console.WriteLine(“n数组中元素的总数是 0,objNames.Length.ToString();/输出数组秩Console.WriteLine(n数组秩是 0,objNames.Rank.ToString();/反转数组并输出Array.Reverse(objNames);Console.WriteLine(“n反转数组后);for(int ctr = 0 ; ctr value是一对一的映射,即根据是一对一的映
209、射,即根据key就可以立刻在集合众找到所需元素就可以立刻在集合众找到所需元素中国城市天气预报中国城市天气预报 书目信息书目信息keyvaluekeyvalue北京北京 “晴晴”ISBN-0110 “红与红与黑黑”上海上海 “小雨小雨”ISBN-0210“荆棘鸟荆棘鸟”广州广州“阴天阴天”ISBN-9106 “简爱简爱”HashTable类类Hashtable方法:方法:Add(key,value)根据根据key而不是根据索引查找,因此速度很快而不是根据索引查找,因此速度很快示例:示例:Hashtableht=newHashtable();/创建创建HashTable/增加对象增加对象ht.Ad
210、d(Beijing,Sunny);ht.Add(ShangHai,Rainy);ht.Add(Guandong,Cloudy);Ht“Guandong”=Cloudy;/读对象读对象stringbjWeather=ht“Beijing”;ContainsKey方法bool keyFound;if(ht.ContainsKey(“Beijing”) keyFound=true;else keyFound=false;列举HashTable中的Keysforeach(string key in ht.Keys) MessageBox.Show(key);列举HashTable中的Valuesfor
211、each(string value in ht.Values) MessageBox.Show(value);列举HashTable中的Keys和Valuesforeach(DictionaryEntry de in ht) MessageBox.Show(de.Key + “ “ + de.Values); 数组和集合的比较数组和集合的比较数组声明了元素类型,但集合没有,因为集合数组声明了元素类型,但集合没有,因为集合中所用元素都存储为对象中所用元素都存储为对象数组的大小是固定的,不能增加和减少;而集数组的大小是固定的,不能增加和减少;而集合类可根据需要动态调整大小合类可根据需要动态调整大小
212、检索元素的方式不同检索元素的方式不同自定义集合是指定制实现自定义集合是指定制实现System.Collections提供的集合接口的集提供的集合接口的集合。下面以合。下面以IEnumerable集合接口为例自定义集合。集合接口为例自定义集合。IEnumerable接口定义:接口定义:publicinterfaceIEnumerableIenumeratorGetEnumerator();实现实现IEnumerable的同时也要实现的同时也要实现IEnumerator接口。接口。IEnumerator接口为:接口为:publicinterfaceIEnumeratorobjectCurrentg
213、et();boolMoveNext();voidReset();自定义集合自定义集合foreach的本质的本质foreach(ElementTypeelementinCollection).IEnumeratorenumerator=(IEnumerable)(collection).GetEnumerator();trywhile(enumerator.MoveNext()ElementTypeelement=(ElementType)enumerator.Current;.IEnumerable自定义集合示例自定义集合示例usingSystem;usingSystem.Collection
214、s;/集合类的命名空集合类的命名空间间namespaceCustomCollection/定义集合中的元素定义集合中的元素MyClass类类classMyClasspublicstringName;publicintAge;/带参构造器带参构造器publicMyClass(stringname,intage)this.Name=name;this.Age=age;/实现接口实现接口Ienumerator和和IEnumerable类类IteratorpublicclassIterator:IEnumerator,IEnumerable/初始化初始化MyClass类型的集合类型的集合private
215、MyClassClassArray;intCnt;publicIterator()/使用带参构造器赋值使用带参构造器赋值ClassArray=newMyClass4;ClassArray0=newMyClass(Kith,23);ClassArray1=newMyClass(Smith,30);ClassArray2=newMyClass(Geo,19);ClassArray3=newMyClass(Greg,14);Cnt=-1;/实现实现IEnumerator的的Reset()方法方法publicvoidReset()/指向第一个元素之前,指向第一个元素之前,Cnt为为 1,遍历是从遍历是
216、从0开始开始Cnt=-1;/实现实现IEnumerator的的MoveNext()方法方法publicboolMoveNext()return(+Cnt castObj.myPrice) return 1; else if (this.myPrice castObj.myPrice) return -1; else return 0; throw new ArgumentException(object is not a Chair); class MyApp static void Main() Chair chairs = new Chair4; chairs0 = new Chair(1
217、50.0, Lane, 99-88); chairs1 = new Chair(250.0, Lane, 99-00); chairs2 = new Chair(100.0, Lane, 98-88); chairs3 = new Chair(120.0, Harris, 93-9); Array.Sort(chairs); /默认只对基本类型排序 foreach (Chair c in chairs) Console.WriteLine(c.myPrice + + c.myVendor + + c.myID); 类型安全类型安全1MySchool中添加一个中添加一个Teacher类类Teac
218、herjacky=newTeacher(成龙龙成龙龙,4);jacky.SayHi();students.Add(jacky);能否加入一个能否加入一个Teacher对象?对象?foreach(Objectstuoinstudents)Studentstu=(Student)stuo;Console.WriteLine(stu.Name);遍历这个集合是否遍历这个集合是否有问题?有问题?演示:演示:MySchool 类型安全类型安全2Student集合集合Scofield张靓靓张靓靓周杰杰周杰杰成龙龙成龙龙添加对象添加对象遍历集合遍历集合对象存储不对象存储不易控制易控制类型转换类型转换容易出错
219、容易出错Teacher对象对象运行错误运行错误什么是泛型集合什么是泛型集合泛型集合可以约束集合内的元素类型泛型集合可以约束集合内的元素类型编译时检查类型约束编译时检查类型约束无需装箱拆箱操作无需装箱拆箱操作加上加上usingSystem.Collections.Generic;List,Dictionary、表示该泛型集合中的元素类型表示该泛型集合中的元素类型ListStudent对象对象Teacher对象对象允许添加允许添加不允许添加不允许添加Student对象对象无需转换类型无需转换类型Liststudents=newList();利用利用List存储班级集合存储班级集合List的使用的使
220、用students.Add(scofield);students.Add(jacky);将将Student对象加入班级对象加入班级将将Teacher对象加入班级对象加入班级编译出错编译出错foreach(Studentstuinstudents)Console.WriteLine(stu.Name);不需类型转换不需类型转换 遍历遍历List集合集合演示:演示:MySchool 只能保存只能保存Student对象对象使用泛型集合使用泛型集合ListStudentstu1=students2;stu1.SayHi();Students.RemoveAt(0);/List方式方式foreach(S
221、tudentstuinstudents)Console.WriteLine(stu.Name);List的访问方式与的访问方式与ArrayList相同相同使用索引访问,无需类型转换使用索引访问,无需类型转换利用索引删除利用索引删除遍历时不需要类型转换遍历时不需要类型转换using System;using System.Collections.Generic;public class Example public static void Main() List dinosaurs = new List(); dinosaurs.Add(Pachycephalosaurus); dinosaur
222、s.Add(Amargasaurus); dinosaurs.Add(Mamenchisaurus); dinosaurs.Add(Deinonychus); dinosaurs.Sort(); dinosaurs.Insert(0, Tyrannosaurus); foreach (string dinosaur in dinosaurs) Console.WriteLine(dinosaur); List与与ArrayList通过索引删除元素通过索引删除元素添加对象方法相同添加对象方法相同通过索引访问集合的元素通过索引访问集合的元素相同点相同点需要装箱拆箱需要装箱拆箱无需装箱拆箱无需装箱拆
223、箱可以增加任何类型可以增加任何类型增加元素时类型严格检查增加元素时类型严格检查不同点不同点ArrayListList异同点异同点是否有是否有哈希表哈希表那样存储那样存储Key和和Value形式的泛型集合呢?形式的泛型集合呢? 访问访问List与与ArrayList的对比的对比Dictionary概述概述Dictionary具有具有List相同的特性相同的特性约束集合中元素类型约束集合中元素类型编译时检查类型约束编译时检查类型约束无需装箱拆箱操作无需装箱拆箱操作与哈希表类似存储与哈希表类似存储Key和和Value的集合的集合Dictionarystudents=newDictionary();利
224、用利用Dictionary存储学员集合存储学员集合Key存储存储String类型类型value存储存储Student类型类型Dictionary的使用的使用students.Add(scofield.Name,scofield);studentstu2=students周杰杰周杰杰;students.Remove(周杰杰周杰杰);添加一对添加一对Key/Value通过通过Key获取元素获取元素通过通过Key删除元素删除元素/Dictionary方式方式foreach(Studentstudentinstudents.Values)Console.WriteLine(student.Name);
225、遍历遍历ValuesDictionary的访问方式与哈希表相同的访问方式与哈希表相同演示:演示:MySchool Dictionary与哈希表与哈希表遍历方法相同遍历方法相同添加对象方法相同添加对象方法相同通过通过Key获取获取Value相同点相同点需要装箱拆箱需要装箱拆箱无需装箱拆箱无需装箱拆箱可以增加任何类型可以增加任何类型增加元素时类型严格检查增加元素时类型严格检查不同点不同点哈希表哈希表Dictionary异同点异同点访问访问Dictionary与与哈希表哈希表的对比的对比泛型的重要性泛型的重要性泛型集合与传统集合相比类型更安全泛型集合与传统集合相比类型更安全泛型集合无需装箱拆箱操作泛
226、型集合无需装箱拆箱操作泛型的重要性泛型的重要性泛型是未来五年的主流技术之一泛型是未来五年的主流技术之一解决了很多需要繁琐操作的问题解决了很多需要繁琐操作的问题提供了更好的类型安全性提供了更好的类型安全性CLR支持泛型支持泛型ZJWCHC第第6章章C#文本处理和文件文本处理和文件IOUnicode.NET默认使用默认使用Unicode编码的编码的charchar类型赋值类型赋值chark=k;chark1=(char)75;char值转换为数值值转换为数值chark=7;intn=(int)k;n=(int)char.GetNumericValue(k);字符及本地化字符及本地化System.G
227、lobalizationchari=i;CultureInfomyCI=newCultureInfo(“az”,false);i=char.ToUpper(i,myCI);字符及其字符及其Unicode分类:分类:Unicode标准将标准将Unicode字符分为字符分为30类。类。UnicodeCategory枚举表示了这些类别。枚举表示了这些类别。char.GetUnicodeCategory()chark=k;intiCat=(int)char.GetUnicodeCategory(k);/UppercaseLetterConsole.WriteLine(char.GetUnicodeCa
228、tegory(k);charcr=n;/ControlConsole.WriteLine(char.GetUnicodeCategory(cr);IsControl指示指定的指示指定的Unicode字符是否属于控制字符类别。字符是否属于控制字符类别。IsDigit指示某个指示某个Unicode字符是否属于十进制数字类别。字符是否属于十进制数字类别。IsHighSurrogate指示指定的指示指定的Char对象是否为高代理项。对象是否为高代理项。IsLetter指示某个指示某个Unicode字符是否属于字母类别。字符是否属于字母类别。IsLetterOrDigit指示某个指示某个Unicode字
229、符是属于字母类别还是字符是属于字母类别还是属于十进制数字类别。属于十进制数字类别。IsLower指示某个指示某个Unicode字符是否属于小写字母类别。字符是否属于小写字母类别。IsLowSurrogate指示指定的指示指定的Char对象是否为低代理项。对象是否为低代理项。IsNumber指示某个指示某个Unicode字符是否属于数字类别。字符是否属于数字类别。IsPunctuation指示某个指示某个Unicode字符是否属于标点符号类字符是否属于标点符号类别。别。IsSeparator指示某个指示某个Unicode字符是否属于分隔符类别。字符是否属于分隔符类别。IsSurrogate指示某
230、个指示某个Unicode字符是否属于代理项字符类别。字符是否属于代理项字符类别。IsSurrogatePair指示两个指定的指示两个指定的Char对象是否形成代理项对象是否形成代理项对。对。IsSymbol指示某个指示某个Unicode字符是否属于符号字符类别。字符是否属于符号字符类别。IsUpper指示某个指示某个Unicode字符是否属于大写字母类别。字符是否属于大写字母类别。Console.WriteLine(char.IsDigit(a);String类类创建字符串:拘留池创建字符串:拘留池(散列表散列表),存储编译期间的所,存储编译期间的所有字符串直接量。有字符串直接量。string
231、poem1=“KublaKhan”;stringpoem2=“KublaKhan”;stringpoem3=String.Copy(poem2);stringpoem4=“Christabel”;Console.WriteLine(poem1=poem2);Console.WriteLine(poem1=poem3);Console.WriteLine(ReferenceEquals(poem1,poem3);Console.WriteLine(ReferenceEquals(poem1,poem2);Console.WriteLine(ReferenceEquals(poem1,KublaK
232、han);比较字符串比较字符串String.CompareintCompare(stringstr1,stringstr2);intCompare(stringstr1,stringstr2,boolIgnoreCase);intCompare(stringstr1,stringstr2,boolIgnoreCase,CultureInfoci);intCompare(stringstr1,intindex1,stringstr2,intindex2,intlen);str1=str2,返回,返回0;str1str2,返回,返回0;str1str2,返回,返回0.strings1=circle
233、;strings2=chair;intresult=String.Compare(s1,s2,true,newCultureInfo(cs-CZ);/-1比较字符串比较字符串String.CompareOrdinal:Unicode码值为判码值为判断大小标准断大小标准strings1=AUTUMN;strings2=autumn;intresult=String.Compare(s1,s2);/1result=String.CompareOrdinal(s1,s2);/-32搜索字符串搜索字符串nstringpoem=“KublaKhan”;poem0;IndexOf,LastIndexOf(
234、string,intstart,intcount)intn=poem.IndexOf(“la”);n=poem.IndexOf(K,4);IndexOfAny,LastIndexOfcharchs=a,e,i,o,u;N=poem.IndexOfAny(chs);N=poem.LastIndexOfAny(chs,2);如果没找到,返回如果没找到,返回-1字符串修改字符串修改Insert(int,string)stringstr=andhestoppeththree;stringverse=str.Insert(str.IndexOf(three),oneof);PadRight,PadLef
235、tstringrem=andsoon;rem=rem.PadRight(rem.Length+3,.);Remove(P,n)Replace(A,B)stringstr=“napacesappath;stringverse=str.Replace(a,i);verse=str.Replace(“a”,“i”);Split(char)stringstr=“red,blueorange;stringsplit=str.Split(newchar,);split2=?ToUpper()ToLower()Trim(),Trim(char)stringstr=“some;str=str.Trim();s
236、tr=str.Trim(,s);TrimEnd(char),TrimStart(char)stringstr=“some;str=str.TrimEnd(e);SubString(n),SubString(n,l)ToCharArray(),ToCharArray(n,l)stringstr=“some;charchs=str.ToCharArray();StringBuilder类类字符串的主要缺点是:每次字符串变量的内容发生改变时,字符串的主要缺点是:每次字符串变量的内容发生改变时,都必须重新分配内存。假设创建一个迭代都必须重新分配内存。假设创建一个迭代100次的循环,每次的循环,每次迭代
237、将一个字符连接到字符串,内存中将有次迭代将一个字符连接到字符串,内存中将有100个字符串。个字符串。StringBuilder类通过分配一个工作区类通过分配一个工作区(缓存缓存)解决这个问解决这个问题。题。usingSystem.Text;StringBuilder操作操作inti=4;charch=w,h,i,t,e;stringmyColor=orange;StringBuildersb=newStringBuilder(redbluegreen);sb.Insert(0,ch);sb.Insert(5,);sb.Remove(0,6);sb.Append(myColor);sb.Repl
238、ace(blue,violet);stringcolors=sb.ToString();Console.WriteLine(sb);usingSystem;usingSystem.Text;publicclassMyAppstaticvoidMain()intstart,end;stringstr=a;start=Environment.TickCount&Int32.MaxValue;for(inti=0;i50000;i+)str+=a;end=Environment.TickCount;Console.WriteLine(end-start);start=Environment.Tick
239、Count&Int32.MaxValue;StringBuildersb=newStringBuilder();for(inti=0;i50000;i+)sb.Append(a);end=Environment.TickCount;Console.WriteLine(end-start);935916除非应用大量文本处理,否则除非应用大量文本处理,否则StringBuilder的优的优势并不明显,此时应使用标准连接操作符。势并不明显,此时应使用标准连接操作符。格式化数据格式化数据String.FormatString.FormatThereare20studentswith75.00%pass
240、ing货币金额格式货币金额格式(C(C或或c)c)字符字符C C(或(或c c)用来将数据转换为货币金额格式。紧跟在字符)用来将数据转换为货币金额格式。紧跟在字符C C后面的数字定义货币金额数据小数点后应保留的位数。如后面的数字定义货币金额数据小数点后应保留的位数。如: : intCurValue=12345678;doublefCurValue=12345678.125;Stringstr1=String.Format(null,”0:C2”,CurValue);Stringstr2=String.Format(null,”0:C2”,fCurValue);结果:结果:¥12,345,678
241、.00¥12,345,678.13整数数据格式整数数据格式(D(D或或d)d) xxxxxxxx字符字符D D(或(或d d)用来将数据转换为十进制数整数格式。紧跟在)用来将数据转换为十进制数整数格式。紧跟在字符字符D D后面的数字则规定了数字将表示的位数。如果这个数字后面的数字则规定了数字将表示的位数。如果这个数字小于整数数据的实际位数,则显示所有的整数位,若这个数小于整数数据的实际位数,则显示所有的整数位,若这个数字大于整数数据的实际位数,则在整数数据的前面用数字字大于整数数据的实际位数,则在整数数据的前面用数字0 0补补足所有的位数。如足所有的位数。如: : intCurValue=12
242、345678;Stringstr1=String.Format(null,”0:D5”,CurValue);Stringstr2=String.Format(null,”0:D9”,CurValue);结果:结果:“12345678”“012345678”科学计数法格式科学计数法格式(E(E或或e)e) x.xxxxE+xxxx.xxxxE+xxx或或x.xxxxE-xxxx.xxxxE-xxx xxxxe+xxx xxxxe+xxx或或x.xxxxe-xxxx.xxxxe-xxx浮点数常数可以使用科学计数法表示(也叫指数形式)浮点数常数可以使用科学计数法表示(也叫指数形式)字符字符E E(或
243、(或e e)用来将数据转换为科学计数法形式。紧跟在字符)用来将数据转换为科学计数法形式。紧跟在字符E E后面的数后面的数字规定小数点后应保留的位数,如果字规定小数点后应保留的位数,如果E E后面没有数字,则小数点后保留后面没有数字,则小数点后保留6 6位位( (有效位数有效位数7 7位位) )。如。如: :doublefCurValue=12345678.125;Stringstr1=String.Format(null,”0:E6”,fCurValue);Stringstr2=String.Format(null,”0:E”,fCurValue);结果:结果:“1.234568E+007”“
244、1.2345678E+007”第第4 4章章 控制台输入和输出控制台输入和输出定点数据格式定点数据格式 xxxxxx.xxxxxxxx.xx字符字符F F(或(或f f)用来将浮点数据转换为定点数据格式。紧跟在)用来将浮点数据转换为定点数据格式。紧跟在字符字符F F后面的数字规定小数点后面应保留的位数,如果指定的后面的数字规定小数点后面应保留的位数,如果指定的数字大于数据小数部分的位数,则在小数点的最后用数字数字大于数据小数部分的位数,则在小数点的最后用数字0 0补补足,如果足,如果F F后面没有数字,则默认为两位小数。如后面没有数字,则默认为两位小数。如: : intCurValue=123
245、45678;doublefCurValue=12345678.125;Stringstr1=String.Format(null,”0:F2”,CurValue);Stringstr2=String.Format(null,”0:F4”,fCurValue);结果:结果:12,345,678.0012,345,678.1250通用数据格式通用数据格式(G(G或或g)g)字符字符G G(或(或g g)用来表示通用数据格式。这个数据可能使用科)用来表示通用数据格式。这个数据可能使用科学计数法来表示,也可能使用定点数据格式表示。在学计数法来表示,也可能使用定点数据格式表示。在VisualC#Visu
246、alC#中,若字符中,若字符G G后面没有数字,即没有规定浮点数的精后面没有数字,即没有规定浮点数的精度,则用定点数据格式;如果度,则用定点数据格式;如果G G后面有指定数字(精度),则后面有指定数字(精度),则用科学计数法表示。用科学计数法表示。doublefCurValue=12345678.125;Stringstr1=String.Format(null,”0:G”,fCurValue);Stringstr2=String.Format(null,”0:G4”,fCurValue);结果:结果:12345678.1251.234E+07自然数据格式自然数据格式(N(N或或n )n )
247、xxx,xxx.xxxxx,xxx.xx字符字符N N(或(或n n)用来表示自然数据格式。这种数据格式是将数)用来表示自然数据格式。这种数据格式是将数据表示成据表示成“xxx,xxx.xxxxx,xxx.xx”,字符,字符N N后面的数字规定了数据格式后面的数字规定了数据格式中小数点后面的数字个数中小数点后面的数字个数intCurValue=12345678;doublefCurValue=12345678.125;Stringstr1=String.Format(null,”0:N”,CurValue);Stringstr2=String.Format(null,”0:N2”,fCurVa
248、lue);结果:结果:12345678.0012345678.13十六进制数格式十六进制数格式(X(X或或x)x)字符字符X X(或(或x x)用来表示十六进制数格式。这种数据格式是将)用来表示十六进制数格式。这种数据格式是将整数转换成整数转换成“xxxxxxxxxxxx”形式的十六进制整数,字符形式的十六进制整数,字符X X后面的数后面的数字规定了格化数据的数字个数字规定了格化数据的数字个数. .intCurValue=123456;Stringstr1=String.Format(null,”0:X”,CurValue);Stringstr2=String.Format(null,”0:X
249、6”,CurValue);结果:结果:1e24001e240日期和时间日期和时间System.DateTimeSystem.DateTime日期和时间类日期和时间类(System.DateTime)C#将日期和时间数据封装在将日期和时间数据封装在DateTime类中类中.生成一个生成一个DateTime类的变量需要使用类的变量需要使用new运算符运算符.也可以也可以用下述方法用下述方法:DateTime(intyear,intmonth,intday);DateTime(intyear,intmonth,intday,inthour,intminute,intsecond);DateTime(
250、intyear,intmonth,intday,inthour,intminute,intsecond,intmillisecond);DateTime类的属性类的属性Now当前时间当前时间Today当前日期当前日期Date返回对象定义的日期返回对象定义的日期Day返回对象定义的日返回对象定义的日(1-31)DayOfWeek返回对象定义日期的星期数返回对象定义日期的星期数(1-7)DayOfYear返回对象中的日在一年中的序号返回对象中的日在一年中的序号(1-365)Hour返回对象定义的小时数值返回对象定义的小时数值()Millisecond毫秒数值毫秒数值Minute分钟数值分钟数值Mo
251、nth月数值月数值Second秒数值秒数值Ticks返回对象定义时间距离返回对象定义时间距离0001年年1月月1日日12:00AM时刻的时刻的100倍纳秒数倍纳秒数TimeOfDay时间值时间值Year年数年数usingSystem;publicclassMyAppstaticvoidMain()DateTimecurDate=DateTime.Now;Console.WriteLine(Date:+curDate);Console.WriteLine(Month:+curDate.Month);Console.WriteLine(Day:+curDate.Day);Console.Write
252、Line(DayOfWeek:+curDate.DayOfWeek);Console.WriteLine(DayOfYear:+curDate.DayOfYear);Console.WriteLine(Hour:+curDate.Hour);Date:2010-2-122:45:11Month:2Day:12DayOfWeek:FridayDayOfYear:43Hour:2正则表达式正则表达式正则表达式提供了功能强大、灵活而正则表达式提供了功能强大、灵活而又高效的方法来处理文本。又高效的方法来处理文本。正则表达式的全面模式匹配表示法使正则表达式的全面模式匹配表示法使您可以快速分析大量文本以找
253、到特定的字符您可以快速分析大量文本以找到特定的字符模式;提取、编辑、替换或删除文本子字符模式;提取、编辑、替换或删除文本子字符串;或将提取的字符串添加到集合以生成报串;或将提取的字符串添加到集合以生成报告。告。对于处理字符串的许多应用程序而言对于处理字符串的许多应用程序而言正则表达式是不可缺少的工具。正则表达式是不可缺少的工具。正则表达式简介正则表达式简介正则表达式:正则表达式:用某种模式去匹配指定字符串的一种表示用某种模式去匹配指定字符串的一种表示方式。方式。正则表达式由普通字符和元字符组成。正则表达式由普通字符和元字符组成。普通字符:普通字符:常使用的字符如字母、数字、汉字等元字常使用的字
254、符如字母、数字、汉字等元字符:可以匹配某些字符形式的具有特殊含义的字符,符:可以匹配某些字符形式的具有特殊含义的字符,其作用类似于其作用类似于DOS命令使用的通配符。命令使用的通配符。正则表达式简介正则表达式简介(续续)1.正则表达式基本书写符号正则表达式基本书写符号2.正则表达式限定符正则表达式限定符3.匹配字符集匹配字符集(1)匹配字符集是预定义的用于正则表匹配字符集是预定义的用于正则表达式中的符号集。达式中的符号集。(2)如果字符串与字符集中的任何一个如果字符串与字符集中的任何一个字符相匹配,它就会找到这个匹配项。字符相匹配,它就会找到这个匹配项。4.分组构造分组构造正则表达式简介正则表
255、达式简介5.正则表达式举例正则表达式举例正整数:正整数:“0-9*1-90-9*$”非负整数:非负整数:“d+$”非正整数:非正整数:“(-d+)|(0+)$”整数:整数:“-?d+$”英文字符串:英文字符串:“A-Za-z+$”英文字符数字串:英文字符数字串:“A-Za-z0-9+$”英数字加下划线串:英数字加下划线串:“w+$”E-mail地址:地址:“w-+(.w-+)*w-+(.w-+)+$”URL:“a-zA-Z+:/(w+(-w+)*)(.(w+(-w+)*)*(?s*)?$”Regex类类Regex类表示不可变(只读)正则表达式类。它还包含类表示不可变(只读)正则表达式类。它还包
256、含各种静态方法,允许在不显式创建其他类的实例的情况下各种静态方法,允许在不显式创建其他类的实例的情况下使用其他正则表达式类。使用其他正则表达式类。Regex类在类在System.Text.RegularExpressions命命名空间下。名空间下。这里仅介绍这里仅介绍IsMatch方法。方法。IsMatch方法:正则表达式在输入字符串中是否找到方法:正则表达式在输入字符串中是否找到匹配项。匹配项。该方法有四种重载的形式:该方法有四种重载的形式:upublicboolIsMatch(stringstr);表示在构造函数中指定的正则表达式在表示在构造函数中指定的正则表达式在str中中是否找到匹配项
257、。是否找到匹配项。upublicboolIsMatch(stringstr,intstart);表示在构造函数中指定的正则表达式在表示在构造函数中指定的正则表达式在str的指的指定起始位置开始是否找到匹配项。参数定起始位置开始是否找到匹配项。参数start表表示开始搜索的字符位置。示开始搜索的字符位置。Regex类类(续续)upublicstaticboolIsMatch(stringstr,stringpattern);表示使用表示使用pattern参数中指定的正则表达式是否在参数中指定的正则表达式是否在str中找中找到匹配项。到匹配项。upublicstaticboolIsMatch(st
258、ringstr,stringpattern,RegexOptionsoptions);表示使用表示使用pattern参数中指定的正则表达式和参数中指定的正则表达式和options枚举枚举提供的匹配选项在提供的匹配选项在input中是否找到匹配项。其中中是否找到匹配项。其中options是是RegexOption枚举值的按位枚举值的按位“或或”组合。组合。Regex类类(续续)例例:Regexr=newRegex(0-9a-z3,5);stringtests=abc,123456,(aa22bb33),ab;foreach(stringtestintests)if(r.IsMatch(test)
259、Console.WriteLine(0中有匹配的项中有匹配的项,test);elseConsole.WriteLine(0中没有匹配的项中没有匹配的项,test);结果结果:ab无匹配项,其他均有匹配项无匹配项,其他均有匹配项textBoxName图7-2 例7-2的设计界面textBoxAgetextBoxPasswordlabelNamelabelAgelabelPasswordbuttonOKusingSystem.Text.RegularExpressions;/更改更改textBoxName.Text属性值触发的事件属性值触发的事件privatevoidtextBoxName_Tex
260、tChanged(objectsender,EventArgse)labelName.Visible=!Regex.IsMatch(textBoxName.Text,u4e00-u9fa52,$);/更改更改textBoxAge.Text属性值触发的事件属性值触发的事件privatevoidtextBoxAge_TextChanged(objectsender,EventArgse)labelAge.Visible=!Regex.IsMatch(textBoxAge.Text,d1,3$);/更改textBoxPassword.Text属性值触发的事件private void textBoxP
261、assword_TextChanged(object sender, EventArgs e) labelPassword.Visible = !Regex.IsMatch(textBoxPassword.Text, w5,$);/单击【确定】按钮触发的事件private void buttonOK_Click(object sender, EventArgs e) if (labelName.Visible | labelAge.Visible | labelPassword.Visible) MessageBox.Show(请按要求输入, , MessageBoxButtons.OK, M
262、essageBoxIcon.Hand); else MessageBox.Show(注册验证成功, , MessageBoxButtons.OK, MessageBoxIcon.Warning); Match类类Match类表示单个正则表达式匹配操作的结果,类表示单个正则表达式匹配操作的结果,得到的结果是只读的。该类没有公共构造函数,而是用得到的结果是只读的。该类没有公共构造函数,而是用Regex对象的对象的Match方法返回的结果创建该类的对象。方法返回的结果创建该类的对象。例如:例如:Regexr=newRegex(abc);Matchm=r.Match(123abc456);if(m.S
263、uccess)Console.WriteLine(找到匹配位置:找到匹配位置:+m.Index);Console.WriteLine(找到匹配结果:找到匹配结果:+m.Value);运行结果:运行结果:找到匹配位置:找到匹配位置:3找到匹配结果:找到匹配结果:abcMatchCollection类类MatchCollection类表示成功的非重类表示成功的非重叠匹配的序列,得到的集合是只读的。该类同样叠匹配的序列,得到的集合是只读的。该类同样没有公共构造函数,而是用没有公共构造函数,而是用Regex.Matches方法返回的结果创建该类的对象。方法返回的结果创建该类的对象。例如:例如:Rege
264、xr=newRegex(abc);MatchCollectionmc=r.Matches(123abc4abcd);intcount=mc.Count;Stringresults=newStringcount;intmatchPosition=newintcount;for(inti=0;icount;i+)resultsi=mci.Value;matchPositioni=mci.Index;Console.WriteLine(第第0个匹配结果:个匹配结果:1,位置:,位置:2,i+1,resultsi,matchPositioni);运行结果:运行结果:第第1个匹配结果:个匹配结果:abc
265、,位置:,位置:3第第2个匹配结果:个匹配结果:abc,位置:,位置:7Group类类Group类表示单个捕获组的结果。当与正则类表示单个捕获组的结果。当与正则表达式匹配的子字符串有多组时,可以使用该类得到表达式匹配的子字符串有多组时,可以使用该类得到某一组的结果。例如:某一组的结果。例如:stringssn=“245-09-8444”;Stringpat=“(d3)-(d2)-(d4)$”;stringtext=Onecarredcarbluecar;stringpat=(w+)s+(car);Regexr=newRegex(pat,RegexOptions.IgnoreCase);Matc
266、hm=r.Match(text);intmatchCount=0;while(m.Success)Console.WriteLine(Match+(+matchCount);for(inti=1;i=2;i+)Groupg=m.Groupsi;Console.WriteLine(string.Format(Group0=1,i,g);CaptureCollectioncc=g.Captures;Group类(续)类(续)for(intj=0;jcc.Count;j+)Capturec=ccj;Console.WriteLine(string.Format(Capture0=1,Position
267、=2,j,c,c.Index);m=m.NextMatch();Console.ReadLine();Group类(续)类(续)输出结果:输出结果:Match1Group1=OneCapture0=One,Position=0Group2=carCapture0=car,Position=4Match2Group1=redCapture0=red,Position=8Group2=carCapture0=car,Position=12Match3Group1=blueCapture0=blue,Position=16Group2=carCapture0=car,Position=21Match
268、,GroupCollection和和CaptureCollecture的关系的关系stringhexPatt=(?a-fA-Fd4)*;反向引用组反向引用组stringspeech=Fourscoreandandsevenyears;pat=(ba-zA-Z+b)s1;/pat=(?ba-zA-Z+b)sk;MatchCollectionmc=Regex.Matches(speech,pat);foreach(Matchmtinmc)Console.WriteLine(mt);/Console.WriteLine(mt.Groupsrepeatand);System.IO:读写数据流的类读写数
269、据流的类Stream类类是派生出各种类的抽象类,处理是派生出各种类的抽象类,处理字节流字节流其中的一些派生类包括其中的一些派生类包括FileStreamMemoryStreamBufferedStreamCryptoStreamFileStream类构造函数类构造函数构造函数构造函数FileStream(stringFilePath,FileMode)FileStream(stringFilePath,FileMode,FileAccess)FileStream(stringFilePath,FileMode,FileAccess,FileShare)与与 FileStream 类一起使用的枚
270、举数类一起使用的枚举数FileMode枚举数枚举数AppendCreateCreateNewOpenOpenOrCreateTruncateFileAccess枚举数枚举数ReadWriteReadWriteFileShare枚举数枚举数NoneReadWriteReadWriteusing System;using System.IO;public class MyApp static void Main() try FileStream fs = new FileStream(C:artistslog.txt, FileMode.OpenOrCreate, FileAccess.ReadW
271、rite); byte alpha = new byte6 65, 66, 67, 68, 69, 70 ; foreach (byte b in alpha) fs.WriteByte(b); fs.Position = 0; for (int i = 0; i fs.Length(); i+) Console.Write(char)fs.ReadByte(); fs.Close(); catch (Exception ex) Console.Write(ex.Message); MemoryStream类类用于从内存中读取数据和将数据写入内存中用于从内存中读取数据和将数据写入内存中以下是以
272、下是 MemoryStream的一些方法的一些方法方法方法Read()ReadByte()Write()WriteByte()WriteTo()using System;using System.IO;public class MyApp static void Main() try FileStream fsIn = new FileStream(C:manet.bmp, FileMode.Open, FileAccess.Read); FileStream fsOut = new FileStream(C:manetcopy.bmp, FileMode.OpenOrCreate, File
273、Access.Write); MemoryStream ms = new MemoryStream(); int imgByte; while (imgByte = fsIn.ReadByte() != -1) ms.WriteByte(byte)imgByte); ms.WriteTo(fsOut); byte imgArray = ms.ToArray(); fsIn.Close(); fsOut.Close(); ms.Close(); catch (Exception ex) Console.Write(ex.Message); BufferedStream类类2-1用于在缓冲区中读取
274、和写入用于在缓冲区中读取和写入当缓冲区满或关闭时,内容将刷新输出到底层流当缓冲区满或关闭时,内容将刷新输出到底层流它有两个重载的构造函数它有两个重载的构造函数语法语法using System;using System.IO;public class BuffStream public void SaveStream() Stream fsOut1 = new FileStream(captured.txt, FileMode.OpenOrCreate, FileAccess.Write); BufferedStream fileBuffer = new BufferedStream(fsOut
275、1); byte buff;/ array to hold bytes written to buffer bool readMore = true; while (readMore) buff = FillBytes();/ Get array of bytes Console.WriteLine(buff16); for (int j = 0; j buff16; j+) fileBuffer.WriteByte(buffj);/ store bytes in buffer if (buff16 16) readMore = false; / indicates no more data
276、fileBuffer.Close(); / flushes all remaining buffer content fsOut1.Close(); / Must close after bufferedstream / method to simulate I/O device receiving data private static byte FillBytes() Random rand = new Random(); byte r = new Byte17; / store random numbers to return in array for (int j = 0; j 16;
277、 j+) rj = (byte)rand.Next(); if (rj = 171) / Arbitrary end of stream value r16 = (byte)(j); / Number of bytes in array return r; r16 = (byte)16; / entire buffer was filled System.Threading.Thread.Sleep(200); / Delay 500ms return r; public class MyApp static void Main() BuffStream bs = new BuffStream
278、(); bs.SaveStream(); Console.WriteLine(Buffered data written.); Console.Read(); CryptoStream类类2-1用于链接数据流与加密对象,以便进行数据加密用于链接数据流与加密对象,以便进行数据加密位于位于 System.Security.Cryptography 命名空间命名空间中中using System;using System.IO;using System.Security.Cryptography;/ CryptoStream examplepublic class MyApp/ Encrypt Fil
279、eStream private static void WriteEncrypt(FileStream fs, string msg) / (1) Create Data Encryption Standard (DES) object. DESCryptoServiceProvider crypt = new DESCryptoServiceProvider(); / (2) Create a key and Initialization Vector - requires 8 bytes crypt.Key = new byte 71, 72, 83, 84, 85, 96, 97, 78
280、 ; crypt.IV = new byte 71, 72, 83, 84, 85, 96, 97, 78 ; / (3) Create CryptoStream stream object CryptoStream cs = new CryptoStream(fs, crypt.CreateEncryptor(), CryptoStreamMode.Write); / (4) Create StreamWriter using CryptoStream StreamWriter sw = new StreamWriter(cs); sw.Write(msg); sw.Close(); cs.
281、Close(); / Read and Decrypt a file stream. private static string ReadEncrypt(FileStream fs) / (1) Create Data Encryption Standard (DES) object. DESCryptoServiceProvider crypt = new DESCryptoServiceProvider(); / (2) Create a key and Initialization Vector crypt.Key = new byte 71, 72, 83, 84, 85, 96, 9
282、7, 78 ; crypt.IV = new byte 71, 72, 83, 84, 85, 96, 97, 78 ; / (3) Create CryptoStream stream object CryptoStream cs = new CryptoStream(fs, crypt.CreateDecryptor(), CryptoStreamMode.Read); / (4) Create StreamReader using CryptoStream StreamReader sr = new StreamReader(cs); string msg = sr.ReadToEnd(
283、); sr.Close(); cs.Close(); return msg; static void Main() / Open file to which encrypted string is written string toEncrypt = Selected site is in Italy.; FileStream fs = null; try fs = new FileStream(corecsharpdatatestcrypt.txt, FileMode.Create, FileAccess.Write); MyApp.WriteEncrypt(fs, toEncrypt);
284、fs = new FileStream(corecsharpdatatestcrypt.txt, FileMode.Open, FileAccess.Read); string msg = MyApp.ReadEncrypt(fs); Console.WriteLine(msg); catch (Exception ex) Console.WriteLine(ex.Message); fs.Close(); Console.Read(); CryptoStream类类2-1用于链接数据流与加密对象,以便进行数据加用于链接数据流与加密对象,以便进行数据加密密位于位于 System.Securit
285、y.Cryptography 命名空间中命名空间中读写文本文件读写文本文件可以用可以用fileStream来读写文本文件,但是来读写文本文件,但是FileStream是通过字节形式来读写数据的,是通过字节形式来读写数据的,要把字节数据转换为文本,要自己处理编码转要把字节数据转换为文本,要自己处理编码转换。换。对于文本文件的读写,通常用对于文本文件的读写,通常用StreamReader类和类和StreamWriter类更类更方便。方便。其底层是通过其底层是通过FileStream实现读写文实现读写文本文件的。本文件的。读取文本文件读取文本文件构造函数构造函数PublicStreamReader(
286、stringpath,Encodingencoding);其中其中path指定要读取的完整文件路径,指定要读取的完整文件路径,encoding指定要使用的字节编码。例如指定要使用的字节编码。例如GB2312,UTF8等编码形式等编码形式using System;using System.IO;using System.Text;namespace ConsoleApplication2 class Class1 /多线程COM时使用MTAThread STAThread static void Main(string args) StreamReader sr = new StreamRead
287、er(c:temp.txt, Encoding.GetEncoding(gb2312); string line; while(line = sr.ReadLine() != null) Console.WriteLine(line); sr.Close(); Console.ReadLine(); 写入文本文件写入文本文件与与StreamReader类对应的类是类对应的类是StreamWriter类,类,它专门用于写入文本文件它专门用于写入文本文件PublicStreamWriter(stringpath,boolappend,Encodingencoding);其中其中path指定要写入的
288、完整文件路径,指定要写入的完整文件路径,append为为false则该文件被改写,如果该文件存在,并且则该文件被改写,如果该文件存在,并且append为为true,则数据被追加到该文件中。否则将,则数据被追加到该文件中。否则将创建新文件。创建新文件。Encoding指定要使用的字节编码。指定要使用的字节编码。using System;using System.IO;using System.Text;namespace ConsoleApplication2class Class1STAThreadstatic void main(string args)StreamWriter sw = n
289、ew StreamWriter(c:temp2.txt, true, Encoding.GetEncoding(gb2312);string data = hello world, how are you;sw.WriteLine(data);sw.Close();目录和文件目录和文件文件操作相关的类文件操作相关的类System.IO名字空间中包含了用于文件操作的相关名字空间中包含了用于文件操作的相关类类File提供用于创建、复制、删除、移动和打开文件的静提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建态方法,并协助创建FileStream对象对象FileInfo提供用于创建、复
290、制、删除、移动和打开文件提供用于创建、复制、删除、移动和打开文件的实例方法,并协助创建的实例方法,并协助创建FileStream对象对象Directory提供用于创建、移动和检索文件夹与子文件提供用于创建、移动和检索文件夹与子文件夹的静态方法夹的静态方法(Directory不可以被继承不可以被继承)DirectoryInfo提供用于创建、移动和检索文件夹与提供用于创建、移动和检索文件夹与子文件夹的实例方法子文件夹的实例方法Path提供了用于操作路径的静态方法。例如获得文件提供了用于操作路径的静态方法。例如获得文件扩展名,从路径中获得文件名等扩展名,从路径中获得文件名等管理文件系统管理文件系统管
291、理文件系统包括管理文件系统包括:文件夹的管理文件夹的管理文件的管理文件的管理具体操作包括具体操作包括:文件夹的创建、删除或移动文件夹的创建、删除或移动文件的创建、删除、复制文件的创建、删除、复制Directory类和DirectoryInfo类1Directory类目录使用 Directory类,可以用目录类创建、移动目录,并可列举目录及子目录的内容。Directory类全部是静态方法。Directory类常用方法见表。Directory类的常用方法类的常用方法方方法法含含义义示示例例CreateDirectory创建目录和子目录创建目录和子目录DirectoryInfodi=Director
292、y.CreateDirectory(c:mydir);Delete删除目录及其内容删除目录及其内容Directory.Delete(c:mydir);Move移动文件和目录内容移动文件和目录内容Directory.Move=(c:mydir,c:mynewdir);Exists确定给定的目录字符串是确定给定的目录字符串是否存在物理上对应的目录否存在物理上对应的目录Directory.Exists(c:mydir);GetCurrentDirectory获取应用程序的当前工作获取应用程序的当前工作目录目录console.WriteLine(CurrentDirectoryis:+currentP
293、ath);SetCurrentDirectory将应用程序的当前工作目将应用程序的当前工作目录设置为指定目录录设置为指定目录Directory.SetCurrentDirectory(c:);GetCreationTime获取目录创建的日期和时获取目录创建的日期和时间间DateTimedt=Directory.GetCreationTime(Environment.CurrentDirectory);GetDirectories获取指定目录中子目录的获取指定目录中子目录的名称名称stringsubdirectoryEntries=Directory.GetDirectories(c:mydir
294、);GetFiles获取指定目录中文件的名获取指定目录中文件的名称称stringfiles=Directory.GetFiles(c:mydir);2DirectoryInfo类类在使用在使用DirectoryInfo类的属性和方法前必须先创建它的对象实例,类的属性和方法前必须先创建它的对象实例,在创建时需要指定该实例所对应的目录。例如:在创建时需要指定该实例所对应的目录。例如:DirectoryInfodi=newDirectoryInfo(c:mydir);DirectoryInfo类的常用方法见表。类的常用方法见表。DirectoryInfo类的常用方法类的常用方法方方法法含含义义示示例
295、例Create创建目录创建目录di.Create();Delete删除删除DirectoryInfo实例所引用实例所引用的目录及其内容的目录及其内容di.Delete();MoveTo将将DirectoryInfo实例及其内容实例及其内容移到新的路径移到新的路径di.MoveTo(c:Programfiles);CreateSubDirectory创建一个或多个子目录创建一个或多个子目录DirectoryInfodi=di.CreateSubdirectory(SubDir);GetDirectories返回当前目录的子目录返回当前目录的子目录DirectoryInfosubdirs=di.G
296、etDirectories();GetFiles返回当前目录的文件列表返回当前目录的文件列表FileInfofiles=di.GetFiles();DirectoryInfo与与Directory的区别的区别Directory是一个实用类,它提供了文件夹操是一个实用类,它提供了文件夹操作的一般方法,每次调用这些方法,都需要通作的一般方法,每次调用这些方法,都需要通过参数来指定当前的操作是针对那个文件夹的过参数来指定当前的操作是针对那个文件夹的(功能类似于(功能类似于API)DirectoryInfo类表示某一个指定的文件夹,类表示某一个指定的文件夹,需要在构造函数中绑定这个文件夹。它的属性需要
297、在构造函数中绑定这个文件夹。它的属性与方法都是针对这个绑定的文件夹而言的。与方法都是针对这个绑定的文件夹而言的。一般而言,对于单一的操作使用一般而言,对于单一的操作使用Directory类类更方便,针对某个特定文件夹的多项操作则使更方便,针对某个特定文件夹的多项操作则使用用DirectoryInfo类更方便。类更方便。常见文件夹操作常见文件夹操作获取当前应用程序的路径获取当前应用程序的路径Console.WriteLine(Directory.GetCurrentDirectory();获取当前计算机所有逻辑驱动器的名称获取当前计算机所有逻辑驱动器的名称stringdrvs=Directory
298、.GetLogicalDrives();foreach(stringdrvindrvs)Console.WriteLine(drv);新建文件夹新建文件夹Directory.CreateDirectory(“c:mydirectory”);删除文件夹删除文件夹Directory.Delete(“C:mydirectory”,true);移动文件夹移动文件夹Directory.Move(“c:temp”,”d:qqtemp”);常见文件夹操作常见文件夹操作获取文件夹信息获取文件夹信息DirectoryInfodInfo=newDirectoryInfo(“c:Winnt”);Console.Wr
299、iteLine(“创建时间:创建时间:”+dInfo.CreationTime.ToLongTimeString();Console.WriteLine(“最近访问时间最近访问时间”+dInfo.LastAccessTime.ToLongDateString();Console.WriteLine(“上级文件夹上级文件夹”,dInfo.Parent.Name);Console.WriteLine(“有子文件夹有子文件夹”+dInfo.GetDirectories().Length.ToString();Console.WriteLine(“包含文件包含文件”+dInfo.GetFiles().
300、Length.ToString();常见文件夹操作常见文件夹操作显示所有子文件夹显示所有子文件夹DirectoryInfodInfo=newDirectoryInfo(“c:WinNT”);DirectoryInfodirs=dInfo.GetDirectories();foreach(DirectoryInfodirindirs)Console.WriteLine(dir.Name);常见文件夹操作常见文件夹操作显示文件夹中的文件显示文件夹中的文件DirectoryInfodInfo=newDirectoryInfo(“c:WinNT”);FileInfofs=dInfo.GetFiles(
301、);foreach(FileInfofindirs)Console.WriteLine(f.Name);常见文件夹操作常见文件夹操作显示文件夹中的文件显示文件夹中的文件(指定扩展名指定扩展名)DirectoryInfodInfo=newDirectoryInfo(“c:WinNT”);FileInfofs=dInfo.GetFiles(“*.exe”);foreach(FileInfofindirs)Console.WriteLine(f.Name);文件管理文件管理File类与类与FileInfo类,与文件夹管理类似,类,与文件夹管理类似,File类是一个实用类,提供了操作文件的静态类是一个
302、实用类,提供了操作文件的静态方法,方法,FileInfo类代表某个具体的文件,提供类代表某个具体的文件,提供了对该文件的属性和操作。了对该文件的属性和操作。常见文件操作常见文件操作复制文件复制文件File.Copy(“c:temp.txt”,“D:temp.txt”,true);删除文件删除文件File.Delete(“c:temp.txt”);确定文件是否存在确定文件是否存在boolb=File.Exists(“c:temp.txt”);常见文件操作常见文件操作获取文件大小获取文件大小FileInfof=newFileInfo(“文件名文件名”);longleng=f.Length;获取文件
303、的扩展名获取文件的扩展名FileInfof=newFileInfo(“文件名文件名”);stringext=f.Extension;stringext2=Path.GetExtension(“路径全名路径全名”);获取路径中的文件名获取路径中的文件名FileInfof=newFileInfo(“文件名文件名”);stringname=f.namestringname22=Path.GetFileName(“路径路径全名全名”);【例例】计算目录的大小。计算目录的大小。usingSystem;usingSystem.IO;publicclassShowDirSizepublicstaticlon
304、gDirSize(DirectoryInfod)longSize=0;/累加当前目录下的文件大小累加当前目录下的文件大小FileInfofis=d.GetFiles();foreach(FileInfofiinfis)Size+=fi.Length;/累加当前目录下的子目录大小累加当前目录下的子目录大小DirectoryInfodis=d.GetDirectories();foreach(DirectoryInfodiindis)Size+=DirSize(di);return(Size);publicstaticvoidMain(stringargs)if(args.Length!=1)Co
305、nsole.WriteLine(Youmustprovideadirectoryargumentatthecommandline.);elseDirectoryInfod=newDirectoryInfo(args0);Console.WriteLine(Thesizeofn0anditssubdirectoriesnis1bytes.,d,DirSize(d); 设置程序启置程序启动参数参数为C:Inetpub,程序运行,程序运行结果如下果如下:Path类用来处理路径字符串,它的方法也全部是静态的。常用方法见表。类用来处理路径字符串,它的方法也全部是静态的。常用方法见表。方方法法含含义义示示
306、例例ChangExtension更改路径字符串的扩更改路径字符串的扩展名展名stringnewPath=Path.ChangExtension(c:test.txt,html);Combine合并两个路径的字符合并两个路径的字符串串stringnewPath=Path.Combine(c:,mydir)GetDirectoryName返回指定路径字符串返回指定路径字符串的目录信息的目录信息stringdir=Path.GetDirectoryName(c:mydirtest.txt);GetExtension返回指定路径字符串返回指定路径字符串的扩展名的扩展名stringext=Path.Ge
307、tExtension(c:mydirtest.txt);GetFileName返回指定路径字符串返回指定路径字符串的文件名和扩展名的文件名和扩展名stringname=Path.GetFileName(c:mydirtest.txt);GetFileNameWithoutExtension返回不带扩展名的指返回不带扩展名的指定路径字符串的文件定路径字符串的文件名名(c:mydirtest.txt);GetFullPath返回指定路径字符串返回指定路径字符串的绝对路径的绝对路径stringfullpath=Path.GetFullPath(test.txt);GetTempPath返回当前系统临
308、时文返回当前系统临时文件夹的路径件夹的路径stringtempPath=Path.GetTempPath();HasExtension确定路径是否包括文确定路径是否包括文件扩展名件扩展名boolhasExt=HasExtension(c:mydirtest.txt);Path类类【例例】演示演示Path类的主要成员。类的主要成员。usingSystem;usingSystem.IO;classTestpublicstaticvoidMain()stringpath1=c:tempMyTest.txt;stringpath2=c:tempMyTest;stringpath3=temp;if(Pa
309、th.HasExtension(path1)Console.WriteLine(0hasanextension.,path1);if(!Path.HasExtension(path2)Console.WriteLine(0hasnoextension.,path2);if(!Path.IsPathRooted(path3)Console.WriteLine(Thestring0containsnorootinformation.,path3);Console.WriteLine(0isthelocationfortemporaryfiles.,Path.GetTempPath();Consol
310、e.WriteLine(0isafileavailableforuse.,Path.GetTempFileName();运行结果如下:运行结果如下:c:tempMyTest.txthasanextension.c:tempMyTesthasnoextension.Thestringtempcontainsnorootinformation.C:DocumentsandSettingsyangmingLocalSettingsTempisthelocationfortemporaryfiles.C:DocumentsandSettingsyangmingLocalSettingsTemptmp55.tmpisafileavailableforuse.请按任意键继续请按任意键继续.知识回顾知识回顾Knowledge Knowledge ReviewReview