深入.NET平台和C#编程

1.理解.NET Framework与C#

1-1:Microsoft.NET框架概述 a.Microsoft.NET介绍 .NET的战略目标是在任何时候(when),任何地方(where)任何工具(what)都能通过.NET的服务获得网络上的任何信息, 享受网络给人们的便捷与快乐. b..NET框架的特点 (1)它是.NET框架类库中一个重要的组成部分 (2).NET框架为我们提供了大量的类库,它是一个巨大的宝藏,.NET应用程序可以使用这些类库进行开发 (3)Visual Studio开发工具也可以使用VB.NET语言开发程序 (4).NET框架支持跨语言开发,只要是.NET框架支持的语言都可以实现相互调用和协作 c..NET框架概述 .NET框架非常强大,主要体现在以下几种: (1)提供了一个面向对象的环境变量,完全支持面向对象编程.提高软件的可复用性、可扩展性、可维护性、灵活性等。 (2)对Web应用的强大支持,如今是互联网的时代,大量的网络应用程序发挥着重要的作用。请查看:www.dell.com (3)对Web Server(Web)的支持,WebServer是.NET非常重要的内容。Hotmail和MSN登录时都要使用Hotmail的账户... (4)Visual Studio是一个世界级的开发工具,它和.NET框架配合,能够方便快捷地开发出多种.NET应用程序, 还可以进行测试、版本控制、Team开发和部署等。 1-2:.NET框架结构 a..框架结构 详细请看P11页 例如: .NET Framework .NET Framework类库 Web窗体 Web Service WinForms ASP.NET ADO.NET和XML类 基本框架类 CLR CLS CTS 如上所示:框架结构中的组件

b.公共语言运行时 (1)CTS(通用类型系统) (2)CLS(公共语言规范) (3).NET编译技术 例如: C#代码【C#编译器】 Microsoft中间语言(MSIL) 【CLR和JIT编译器】--------平台专用代码 VB.NET代码【VB.NET编译器】 c.框架类库 框架类库中的核心部分包括以下几点: (1)基础数据的类库,例如String类、集合、泛型等。 (2)I/O访问,主要用于操作文件。 (3)安全控制,为.NET安全机制提供一系列的功能。 (4)数据访问,利用ADO.NET开发数据库的应用程序。 (5)XML是用于描述数据的一种文件格式,它是.NET框架中很重要的一部分。 1-3:C#语言概述 a.C#语言的诞生 2000年,配合.NET平台的发布,微软公司发布了一门新语言:C#。它是专门为.NET平台设计的一种语言, 它的设计者Anders Hejlsberg是一位颇具传奇色彩的人物。牛人:Anders Hejlsberg b.C#锐利体验 (1)微软公司已经向ECMA申请将C#作为一种标准。 (2)完全的面向对象设计,在C#类型系统中,每种类型都可以看到一个对象。 (3)C#从2.0版本开始,对泛型提供了更完整的支持,泛型是微软重点推出的内容,它可以使我们程序更加安全,代码清晰,易控制。 (4)现如今,Web开发已经成为软件业的重点内容,并且C#语言与Web应用开发紧密地结合在一起。 (5)强大的类库支持,C#有着数量庞大、功能齐全的类库支持,可以简单地完成复杂的加密操作、网络应用操作等。 使用C#可以轻松地构建功能强大、开发快捷、运用方便的应用程序。 (6)可以利用C#开发多种应用程序,如Windows程序、ASP.NET、WebService等 例如: ASP.NET Windows Service C# Windows程序 Web服务 如上所示:C#开发多种应用程序

1-4:体检框架类库德强大功能 a.类库的使用 例如: using System.Net; using System.Net.NetworkInformation;//引入命名空间 private void btnPing_Click(object sender,EventArgs e) { Ping pingSender=new Ping();//实例化Ping类 PingReply reply=pingSender.Send(txtIP.Text);//调用方法 if(reply.Status==IPStatus.Success) { string message=string.Format("地址:{0}连接测试成功!",txtIP.Text); MessageBox.Show(message); } else { string message=string.Format("地址:{0}连接测试失败!",txtIP.Text); MessageBox.Show(message); } } b.框架类库中的命名空间 框架类库的内容被组织成一个树状命名空间(Namespace Tree).每一个命名空间可以包含许多类型及其其他命名空间。 System:"树"的根 System.Data用于访问ADO.NET System.Security提供系统的安全控制功能 System.Windows.Forms用于开发Windows应用程序,引入这个命名空间才能使用WinForms的控件和各中特性 System.Collections.Generic可以使用泛型 System.Net可以对网络协议进行编程 c.定义自己的命名空间 using System; using System.Collections.Generic; using System.Text;

namespace MySchool { public class Student { } } d.命名空间的使用 (1)用自定义命名空间组织类 语法: namespace MySchool { class Student { //类的内容 public void Study(){} } } (2)引用命名空间 例如:using System.using MySchool (3)使用命名空间 使用命名空间中的类的方法是命名空间的名字加上"."再加上要使用的类名。例如:MySchool.Student; 使用时逐级地用"."连接,如:City.MySchool.Class.Student stu=new City.MySchool.Class.Student(); (4)命名空间的别名 例如: using System; using System.Collections.Generic; using user=City.MySchool.Class;//指定别名 namespace MyShool { class Student { user.Student stu=new user.Student();//使用别名调用 } }

2.用对象思考:属性和方法

2-1:类和对象 a.一切皆对象 万物皆对象 b.类和类的成员 (1)类的属性 (2)类的方法 c.类和对象的关系 类和对象有着本质上的区别,定义了一组概念的模型,而对象是真实存在的实体,它们之间的关系如下: (1)由对象归纳为类,是归纳对象共性的过程 (2)在类的基础上,将状态和行为实体化为对象的过程称为实例化 d.类和对象的使用 (1)将类实例化为对象 (2)访问对象的属性或者方法 例如: Car ferrari=New Car();//实例化对象 Ferrari.Run();//调用方法或属性 2-2:编写一个自己的类 a.定义类和类的成员 语法: 访问修饰符 class <类名> { //类的主体 } 例如: public class Student { int age=26; //姓名 private string name; public string Name { get{return name;} set{name=value;} } //问候 public void SayHi() { string message; message=string.Format("大家好,我是{0}同学。",name); MessageBox.Show(message); } } 注意: (1)字段用来表示类和对象相关联的数据 (2)属性用来表示类的状态 (3)方法用来标识类的行为 b.在类中添加属性 例如: class Student { private string name;//姓名 public int age;//年龄 public string idNumber;//身份证号 } (1)访问修饰符(2)数据安全(3)如何使用C#属性(4)使用属性的注意事项(5)属性的类型(6)在编码中如何快速地创建属性(7)封装 例如: (1)避免使用非法数据赋值 (2)保证数据的完整性 (3)避免类内部发生修改时,导致整个程序的修改 c.在类中使用方法 语法: 访问修饰符 返回类型 方法名(参数) { //方法体 } 例如: private static void AddSocre(ref int refScore,out int scoreResult) { if(refScore>50 && refScore<60) { Console.WriteLine("你的成绩在50-60之间,可以加分。"); refScore=60; } scoreResult=refScore; } (1)方法的返回值(2)方法的参数(3)使用方法(4)方法的重载(5)静态方法和实例方法 静态方法 实例方法 static关键字 不需要static关键字 类名调用 实例对象调用 可以访问静态成员 可以直接访问静态成员 不可以直接访问实例成员 可以直接访问实例成员 不能直接调用实例方法 可以直接调用实例方法和静态方法 调用前初始化 实例化对象时初始化 d.使用构造函数创建对象 (1)构造函数的使用 (2)this关键字 使用构造方法请注意以下几个问题: 一个类的构造函数名通常与类名相同 构造函数没有返回值 一般情况下,构造函数总是public类型的 在构造函数中不要对类的示例做初始化以外的事情,不要尝试显示的调用构造函数,也就是直接去调用。 2-3:综合实战 (1)设计新闻阅读器的类 (2)命名规范

3.用对象思考:值类型和引用类型

3-1:在类中使用几种新的数据类型 a.在程序中使用常量 例如: public class Compute { double pi=3.14; //计算圆的周长 public double Perimeter(double radius) { return 2*pi*radius; } //计算圆的面积 public double Area(double radius) { return pi*radius*radius; } } 语法: 访问修饰符 const 数据类型 常量名=值 例如 const int MAX_AGE=100; 但是,我们什么时候使用常量呢? (1)用于在程序中一旦设定就不允许被修改的值 (2)用于在程序中被经常引用的值 b.使用枚举避免不合理的赋值 (1)使用枚举的妙处 例如: //... const string GENDER_M="男"; const string GENDER_F="女"; private string gender; public string Gender { get{return gender;} set{gender=value;} } //... 例如: public enum Genders//定义一个枚举 { Male,Female } private Genders gender; public Genders Gender { get{return gender;} set{gender=value;} } //... //使用枚举赋值 student.Gender=Genders.Male; //也可以这样写? student.Gender="ACCP";//这样赋值是不能通过编译的 (2)给枚举成员赋值 例如: public enum Genders { Male=0,Female=1 } static void Main(string[] args) { stu.Gender=Genders.Male;

int genderNum=(int)stu.Gender; swtch(genderNum) { case 0: Console.WriteLine("您输入的性别是-男"); break; case 1: Console.WriteLine("您输入的性别是-女"); break; } } 注意: 程序中还可以获取它的字符串表示 如:Console.WriteLine("您输入的性别是{0}",stu.Gender.ToString()); 我们还可以从一个字符串中获取枚举的值 如:stu.Gender=(Genders)(Enum.Parse(typeof(Genders),"Female")) Console.WriteLine("您输入的性别是{0}",stu.Genders.ToString()); 要从字符串转换,需要使用Enum.Parse(),这个方法第一个参数是关键字typeof后跟放在括号中的枚举类型, 第二个参数是要转换的字符串。在方法最外面要使用枚举类型进行强制转换。 经验: 枚举可以使代码易于维护,有助于确保给变量指定合法的、期望的值。 枚举更易于输入,如果我们使用枚举赋值,则只要输入枚举名,然后打一个"."就能将所有的值显示出来,减少了按键次数, 能够然我们回忆起可选的值。 枚举使代码更清晰,允许描述性的名称表示数据,使用时直观方便 (3)我们曾经使用过的枚举 例如: DialogResult choice; choice=MessageBox.Show("确定退出吗?","退出系统",MessageBoxButtons.OKCancle,MessageBoxIcon.Information); if(choice==DialogResult.OK) { Application.Exit(); } OK:代表确定 Cancle:代表取消 c.它不是一个"类"---结构 (1)结构的定义 语法: 访问修饰符 struct 结构名 { //定义结构成员 } 例如: struct StructStudent { public string Name; public Genders Gender; public int Age; public string Hobby; public int Popularity; public void SayHi() { ; }

} 注意:定义结构时的数据字段是不能赋初值的。 (2)结构的使用 例如: //... StructStudent myStu;//无需new myStu.Age=20; myStu.Gender=Genders.Female; myStu.Hobby="唱歌歌"; myStu.Name="张靓靓"; myStu.Popularity=100; //...

例如: stuct StructStudent { //... public StructStudent(string name,Genders gender,int age,string hobby,int popularity) { this.Name=name; this.Gender=gender; //... } } (3)结构和类的区别 类 结构 引用类型 值类型 可以被继承 不能被继承 可以有默认构造函数 不可以有默认构造函数 可以添加无参的构造函数 可以添加构造函数,但它们必需带参数 创建对象必需使用new 创建对象可以不用new 类中可以给字段赋值 结构中给字段赋值是错误的

都可以包含字段、方法 都可以实现接口

3-2:理解C#中的值类型与引用类型 a.值类型 b.引用类型 c.装箱和拆箱 例如: static void Main(string[] args) { ` `int i=123; object o=i;//装箱 i=456;//改变i的内容 Console.WriteLine("值类型胡值为:{0}",i); Console.WriteLine("引用类型胡值为:{0}",o); }

例如: static void Main(string[] args) { int i=123; object o=i;//隐式装箱 try { int j=(int)o;//拆箱 System.Console.WriteLine("取消装箱成功."); } catch(System.InvalidCastException e) { System.Console.WriteLine("{0}错误:不正确胡取消装箱.",e.Message); } } d.不同类型的参数传递 (1)值方式参数传递 (2)引用方式参数传递 例如: private void Vote(StructStudent stu) { stu.Popularity++; } //... StructStudent scofield=new StructStudent("",Genders.Male,28,"越狱狱"); scofield.SayHi(); Vote(scofield);//将值类型胡学员传递给这个方法 scofield.SayHi(); //...

例如: private void Vote(Student stu) { stu.Popularity++; } //... Student scofield=new Student("Scofield",Genders.Male,28,"越狱狱"); scofield.SayHi(); Vote(scofield);//人气累加 scofield.SayHi(); 注意:虽然我们没有使用ref方式传递,但是参数椒引用类型,当引用变量发生变化时,参数发生了变化。 所以,当类作为参数的时候,可能修改类成员赋值。

(1)引用方式传递引用类型 例如: private void Vote(ref Student stu) { stu.Popularity++; } (2)引用方式传递值类型 例如: private void Vote(ref StructStudent stu) { stu.Popularity++; } e.细分值类型和引用类型 值类型 基本数据类型 整型 int 长整型 long 浮点型 float 字符型 char 布尔型 bool 枚举 enum 结构 struct 引用类型 类 基类 System.Object、字符串 string、自定义类 class 接口 interface 数组 int[]、string[] 例如: private void TestArrayParameter() { int[] odd={1,3,5}; PrintArray(odd);//打印结果 ChangeToEven(odd); PrintArray(odd);//打印结果 } private void ChangeToEven(int[] arr) { for(int i=0;i<arr.Length;i++) { arr[i]=i*2; } } 输出结果如下: arr[0]=1; arr[1]=3; arr[2]=5; arr[0]=0; arr[1]=2; arr[2]=4;

3-3:在类中使用索引器 a.索引器的使用 例如: public Student this[int index] { get{return students[index];} } public Student this[string name] { get { int i; bool found=false; for(i=0;i<students.Length;i++) { if(student[i].Name==name) { found=true; break; } if(found) { return student[i]; } else { return null; } } } } 访问Student对象时,可以通过学员胡姓名访问,也可以通过索引访问。 MyClass myClass=new MyClass("T01"); myClass.Student[2].SayHi(); myClass.Students["黄超华"].SayHi(); b.索引器的特点及其应用 注意:定义一个索引器胡时候,要使用this关键字,而get和set访问器也类似于属性。索引器和数组属性有些类似,但是 数组属性只能通过下标(索引)访问,而索引器可以通过重载它,从而自定义它的访问方式。

3-4:使用类图描述和类成员 描述类成员.如:属性、方法... 详细请看P77页

4.用集合组织相关数据

4-1:集合概述 a.ArrayList (1)给ArrayList添加元素 语法: public int Add(Object value) (2)存储ArrayList中胡单个元素 例如: Student stu1=(Student)students[0]; stu1.SayHi(); (3)删除ArrayList中的元素 删除ArrayList的元素有以下三种方式: 通过RemoveAt(int index)方法删除指定index元素 通过Remove(object value)方法删除一个指定对象名胡元素 通过Clear()方法一移除集合中所有元素 例如: //清除所有元素 students.Clear();

//打印集合数目 MessageBox.Show(string.Format("共包括{0}个学员。",students.Count.ToString())); (4)遍历ArrayList中胡元素 例如: static void Main() { int[] array=new int[]{0,1,2,3,4}; for(int i=0;i<array.Length;i++) { Console.WriteLine(array[i]); } }

例如: //for循环遍历 for(int i=0;i<students.Count;i++) { Student stuFor=(Student)students[i]; Console.WriteLine(stuFor.Name); } //foreach循环遍历 foreach(Object stuo in students) { Student stuForeach=(Student)stuo; Console.WriteLine(stuForeach.Name); } (5)常见错误 将Student类改为了Student结构 数组越界 删除数据后,ArrayList的索引会自动分配和调整 b.HashTable (1)给哈希表添加元素 语法: public void Add(Object key,Object value) (2)获取哈希表的元素] 例如: //使用Add()方法添加元素 students.Add(scofield.Name,scofield); students.Add(zhang.Name,zhang); students.Add(jay.Name,jay); //获取指定的元素 Student stu2=(Student)students["周杰杰"]; stu2.SayHi(); (3)遍历哈希表 例如: students.Add(scofield.Name,scofield); students.Add(zhang.Name,zhang); students.Add(jay.Name,jay); Student stu2=(Student)students["周杰杰"]; stu2.SayHi();

//元素遍历 foreach(Object stuno in students.Values) { Student stu=(Student)stuo; Console.WriteLine(stu.Name); } (4)删除哈希表胡元素 语法: public void Remove(Object key)

students.Add(scofield.Name,scofield); students.Add(zhang.Name,zhang); students.Add(jay.Name,jay); Student stu2=(Student)students["周杰杰"]; stu2.SayHi();

//元素遍历 foreach(Object stuno in students.Values) { Student stu=(Student)stuo; Console.WriteLine(stu.Name); } //删除元素 students.Remove("周杰杰"); 4-2:泛型与泛型集合 a.泛型 泛型有以下两大优点: (1)泛型胡性能高 (2)泛型胡另一个优点是类型安全 b.泛型集合List<T> 语法: 定义一个List<T>泛型集合胡方法如下 List<Student> students=new List<Student>(); 例如: //访问单个元素 //通过索引访问,无须类型转换 Student stu1=students[2]; stu1.SayHi(); //打印集合数目 MessageBox.Show(string.Format("共包括{0}个成员。",students.Count.ToString())); //通过索引删除 students.RemoveAt(0); //打印集合数目 MessageBox.Show(string.Format("共包括{0}个成员。",students.Count.ToString())); foreach(Student stu in students) { //遍历时无需类型转换 Console.WriteLine(stu.Name); } List<T>与ArrayList的区别: List<T> ArrayList 对所保存胡元素做类型约束 啄增加任何类型 添加/读取无须拆箱、装箱 添加/读取需要拆箱、装箱

通过索引访问集合中的元素 添加元素方法相同 删除元素方法相同 c.泛型集合Dictionary<K,V> 语法: 定义一个Dictionary<K,V>泛型集合胡方法如下所示: Dictionary<String,Student> students=new Dictinary<String,Student>(); Dictionary<K,V>和哈希表胡对比: Dictionary<K,V> HashTable 对所保存元素做类型约束 可以增加任何类型 添加/读取无需拆箱、装箱 添加/读取需要拆箱、装箱 通过Key获取Value 添加原始方法相同 删除元素方法相同 遍历方法相同 d.泛型总结 泛型的重要性体现在一下几点: (1)解决国很多频繁的操作问题 (2)提拱了更好的类型安全性 (3)CLR可以支持泛型,这样使得.NET平台都能够使用泛型 4-3:综合实战 RSS阅读器 5.文件读写与XML

5-1:文件 a.文件的应用 例如: .docx .RTF .TXT .XLS .HTML .PDF .TIFF .PSD .JPG .GIF .RAR .MP3 等等... b.如何读写文件 (1)创建一个文件流 (2)创建阅读器或写入器 (3)执行读写操作 (4)关闭阅读器或者写入器 (5)关闭文件流 注意:导入命名空间 using System.IO; 例如: private void btnWrite_Click(object sender,EventArgs e) { string path=txtFilePath.Text; string content=txtContent.Text; if(String.IsNullOrEmpty(path)==true) { MessageBox.Show("文件路径不能为空"); return; } try { //创建文件流 FileStream myFs=new FileStream(path,FileMode.Create); //创建写入器 StreamWriter mySw=new StreamWriter(myFs); //将录入胡内容写入文件 mySw.Write(content); //关闭写入器 mySw.Close(); //关闭文件流 myFs.Close();

MessageBox.Show("写入成功"); } catch(Exception ex) { MessageBox.Show(ex.Message.ToString()); } } c.文件流 Creat 用于指定的名称新建文件。如果文件存在,则会改写旧文件。 CreateNew 新建一个文件。 OpenOrCreat:OpenOrCreate与Open成员类似,只是如果文件不存在,则用指定胡名称新建一个文件夹并打开它。 (1)新建文件流 (2)关闭文件流 d.文件读写器 (1)StreamWriter写入器 StreamWriter mySw=new StreamWriter(myfs); StreamWriter.Write();用于写入流,这个流就是我们创建好的流。 StreamWriter.WriteLine();用于写入一行数据,写入某些数据后跟换行符。 StreamWriter.Close();用于关闭写入器。 (2)StreamReader读取器 StreamReader.ReadLine();读取文件流中的一行数据,并返回字符串。 StreamReader.ReadToEnd();从当前位置读到末尾,返回字符串。 StreamReader.Close();用于关闭读取器。 例如: private void btnRead_Click(object sender,EventArgs e) { string path=txtFilePath.Text; string content; if(String.IsNullOrEmpty(path)==true) { MessageBox.Show("文件路径不能为空"); return; } try { //创建文件流 FileStream myfs=new FileStream(path,FileMode.Open); //创建读取器 StreamReader mySr=new StreamReader(myfs); //读取文件所有内容 content=mySr.ReaderToEnd(); txtContent.Text=content; //关闭读取器 mySr.Close(); //关闭文件流 myfs.Close(); } catch(Exception ex) { MessageBox.Show(ex.Message.ToString()); } }

例如: //直接写入方式 StreamWriter mySw=new StreamWriter(path); mySw.Write(content); mySw.Close();

//直接读取方式 StreamReader mySr=new StreamReader(path); content=mySr.ReadToEnd(); txtContent.Text=content; mySr.Close(); e.文件和目录操作 File类胡方法 Exists(String path) Copy(string SourceFilePath,string DestinationFilePath) Move(string sourceFileName,string destFileName) Delete(string path) Directory类的方法 Exists(string path) Move(string sourceDirName,string destDirName) Delete(string,bool) 静态类与非静态类 静态类 非静态类 用static 不用static修饰 只包含静态成员 可以包含静态成员 不可以包含实例成员 · 可以包含实例成员 使用类名调用静态成员 使用实例对象调用非静态成员 不能被实例化 可以被实例化 不能包含实例构造函数 包含实例构造函数 5-2:新闻阅读器工作原理概述 a.新闻阅读器工作原理 RSS阅读器 b.XML概述 (1)保存 (2)说明数据【用途、关系】 例如: <Student> <Name>张靓颖<Name/> <Age>20</Age> <Hobby>唱歌歌</Hobby> <!-- --> <Name>周杰杰<Name/> <Age>22</Age> <Hobby>耍双节棍棍</Hobby> </Student> 操作XML的对象属性和方法 XmlDocument属性和方法 DocumentElement属性(获取根节点) ChildNode属性(获取所有字节点) Load()方法(读取整个XML的结构) XmlNode的属性和方法 InnerText属性(当前节点的值) Name属性(当前节点胡名字) ChildNodes属性(当前节点的所有字节点) 5-3:操作XML实现抓取新闻功能 a.遍历XML 详细请看P131页 b.TreeView树形控件 例如: private void btnLoadProfile_Click(object sender,EventArgs e) { pm.Load();//读取配置文件 //遍历频道集合 for(RssFeed feed in pm.Profile.Feeds) { TreeNode feedNode;//定义一个TreeView节点 //将一个频道标题加入节点 feedNode=tvMain.Nodes.Add(feed.DisplayName); foreach(Article atcl in feed.Articles.Values) { //在当前频道节点上添加文章标题节点 feedNodes.Nodes.Add(atcl.Title); } } }

6.用对象思考:继承

6-1:继承概述 a.移除类中的冗余代码 例如: 在定义Student和Teacher类的类名后面都多出国":Person":class Student:Person,Class Teacher:Person. 我们称这种方式叫做类的继承。 b.什么是继承 一个类只能继承另一个类 基类、父类 子类、地、派生类 满足 is-a关系 c.继承的实际应用 d.protected访问修饰符与base关键字 例如: //在Person类中修改变量的访问修饰符 protected string name; protected int age; protected Genders gender; //Student的构造函数 public Student(string name,Genders gender,int age,string hobby,int popularity) { this.name=name; this.age=age; this.gender=gender; //学生类扩展的属性 this.hobby=hobby; this.popularity=popularity; }

6-2:继承的使用 a.继承的特型 (1)继承的单根性 (2)继承的传递性 (3)密封性 b.编写子类构造函数的注意事项 (1)隐式调用父类的构造函数 (2)显式调用父类的构造函数 c.继承的价值 (1)继承模拟了显示世界的关系,OOP中强调一切皆对象,符合我们的面向对象思维。 (2)继承实现了代码的重用性,代码更加清晰。 (3)继承使得代码结构清晰。 6-3:综合实战 a.扩展新闻快客 RSS阅读器 (1)支持RSS/Atom两种格式 (2)继承机制给程序带来的变化 b.窗体继承 (1)首先创建基本窗体 (2)实现继承窗体 (3)在父类窗体中实现公共的方法,例如退出等。 例如: partial class ChannelInfoAddForm:MyNewsReader.UI.ChannelInfoFormBase { //省略了窗体中的内容 } 7.用对象思考:多态

7-1:面向对象的多态性 a.巧妙解决继承带来的问题 不同的对象对于同一个方法调用,却有着不同的执行结果,我们称这种特性为多态。 b.什么是多态 多态是指两个或多个属于不同类的对象,对于同一个消息(方法调用)作出不同响应的方式。

7-2:使用抽象类和抽象方法实现多态 a.抽象类和抽象方法 语法: 访问修饰符 abstruct 返回类型 方法(); 语法: 访问修饰符 abstruct class 类名; (1)抽象方法是一个没有实现的方法,通过在定义方法时增加关键字abstruct可以声明抽象方法。 (2)含有抽象方法的类必然是抽象类。同样,我们用abstruct关键字来定义一个抽象类。 b.常见错误 (1)对于一个抽象类有一个限制:它不能被实例化。 (2)抽象类不能是密封或静态的。 c.抽象类和抽象方法的使用 (1)重写抽象方法 (2)去掉获取新闻列表功能中的多余判断 (3)抽象类和抽象方法的应用场合 语法: 访问修饰符 override 返回类型 方法() 什么时候使用抽象类和抽象方法呢? 例如: 猫和狗继承自动物类,猫能喵喵地叫,狗能汪汪地叫,如果动物类是一个抽象类,它里面有一个抽象方法"叫",理解为:是动物都会叫。

d.里氏替换原则 (1)is操作符的使用 语法: if(obj is string) { } 例如: //判断频道是否是RSS类型 if(pm.Profile.Feeds[node.Index] is RssFeed) { rssFeed=(RssFeed)pm.Profile.Feeds[node.Index]; if(rssFeed.FetchArticles()) { UpdateArticlesView(node.Index); } } (2)as操作符的使用 获取元素进行类型转换。 7-3:使用虚方法实现多态 a.为什么要使用虚方法 例如:大家好,我是某某先生(女士),今年多少岁!!这个公告的SayHi()方法应该放在哪里呢? b.虚方法的实际应用 (1)使用需方法实现多态 语法: 访问修饰符 virtual 返回类型 方法() { //方法体 } (2)重新Equals()方法 语法: public virtual bool Equals(Object obj0) 需方法与抽象方法的区别: 需方法 抽象方法 用virtual修饰 用abstract修饰 要有方法体,哪怕是一个分号 不允许有方法体 可以被子类override 必须被子类override 除了密封类外都可以写 只能在抽象类中 c.面向对象的三大特性 (1)封装:保证对象自身数据的完整性、安全性。 (2)继承:建立类之间的关系,实现代码复用,方便系统胡扩展。 (3)相同的方法调用可以实现不同的实现方式。 7-4:简单工厂设计模式概述 详细请看P197页 a.自动识别RSS与Atom b.简单工厂设计模式

8.用对象思考:接口

8-1:接口 a.自定义对象的排序 注意:sort()方法,默认是升序的哈!! b.IComparable接口 语法: public interface IComparable { int CompareTo(Object obj); } 注意: 如果返回值小于0,则当前实例小于obj; 如果返回值大于0,则当前实例大于obj; 如果返回值等于0,则当前实例等于obj; 例如: class Student:Person,IComparable { //... //实现IComparable接口中的方法 public int CompareTo(object obj) { //判断比较对象是否是Student对象 if(!(obj is Student)) { throw new Exception("只能与Student对象比较"); //将参数转换为Student对象 Student other=obj as Student; return this.Name.CompareTo(other.Name); } } } c.接口概述 接口就是一套规范,满足这个规范的设备,我们可以将它们组装在一起,从而实现该设备的功能。 (1)接口可以包含字段、属性、方法、索引器等。但是不能实现,接口中的方法和属性。 例如: 方法 public interface ISampleInterface { void ShowName(); } 属性 public interface ISamepleInterface { string Name { get; set; } } (2)定义一个接口的名称通常以"I"开头 例如:IComparable、IList (3)我们习惯的说法是实现了一个接口、继承了一个类 (4)实现一个接口的语法与继承类似:class Student:IComparable (5)如果类已经继承了一个父类,则以","分割父类和接口 无序之分 (6)class Student:Person,IComparable 如果有父类必须先继承父类再实现接口,实现接口无顺序之分哈! d.接口小结 (1)接口是对继承的单根性的扩展,通过实现多个接口可以说是实现了一个类的多重继承。 (2)接口是一中标准和规范 (3)接口屏蔽了实现的细节 比如:只定义,无需实现,也不能实现。 (4)接口得使用方便团队开发协助

8-2:泛型接口 a.典型泛型接口IComparable<T>的应用 例如: class Student:Person,IComparable<Student> { //省略了构造函数和属性 //IComparable<Student>成员参数必须是Student类型 public int CompareTo(Student other) { //比较返回结果,无需类型转换 return this.Name.CompareTo(other.Name); } } b.IComparer<T>比较器 (1)Sort()方法的重载---Sort(IComparer<T>) 语法: public void Sort(IComparer<T> comparer) (2)IComparer<T>泛型接口 如果返回值大于0,则x>y. 如果返回值小于0,则x<y. 如果返回值等于0,则x=y. c.综合实战 RSS阅读器 详细情看P219页 8-3:接口的典型应用 a.接口作为参数的意义 接口作为参数传递时,实际上要传递的就是实现这个接口的对象。在排序方法里,调用集合的Sort()方法传递的就是实现了 IComparer<T>接口的类的一个对象:students.Sort(New NameComparer); b.接口作为返回值的意义 接口是一组规范、一种标准,必须实现接口才能实现某个功能。典型的应用就是接口作为参数时,我们要传递一个实现接口的 对象,另一个就是将接口作为返回值,实际上要返回的也是实现了接口的对象。 c.接口和抽象类 抽象类与接口的区别 抽象类 接口 用abstract定义 用interface定义 只能继承一个类 可以实现多个接口 非抽象派生类必须实现抽象类 实现接口的类必须实现所有成员 需要override实现抽象方法 直接实现

不能实例化 包含未实现的方法 派生类必须实现未实现的方法

9.序列化与反射

9-1:序列化与反序列化 a.扩展配置信息 注意: 在ProfileManager类中引入这样一个命名空间 using System.Runtime.Serialization.Formatters.Binary; 语法: [Serializable] abstract class FeedBase { //... } 例如: public void Save { FileStream fileStream=null; //定义一个文件流 fileStream=new FileStream("profile.bin",FileMode.Create); //二进制方式 BinaryFormatter bf=new BinarryFormatter(); //序列化保存配置文件对象Profile bf.Serialize(fileStream,Profile); } public void Load() { FileStream fileStream=null; fileStream=new FileStream("profile.bin",FileMode.Open); BinaryFormatter bf=new BinaryFormatter(); Profile=(Profile)bf.Deserialize(fileStream); } b.特性 语法: [Serializable] abstract class FeedBase { //... } 例如: class Program { [Obsolete("不要使用旧的方法,请使用新的方法"),true] static void Old(){} static void New(){} public static void Main() { Old(); } } c.序列化 语法: pubilc void Serialize(Stream serializationStream,Object graph) serializationStream是指定序列化过程的文件流 graph是要保存的对象 例如: FileStream fileStream=nulll; //定义一个文件流 fileStream=new FileStream("profile.bin",FileMode.Create); //二进制方式 BinaryFormatter bf=new BinaryFormatter(); //序列化保存配置文件对象Profile bf.Serialize(fileStream,Profile); d.反序列化 语法: public Object Deserialize(Stream serializationStream) 注意:Deserialize()方法将存储介值的数据文件流转换为Object,通常我们需要进一步将这个Object转换为相应的对象类型。 例如: public void Load() { FileStream fileStream=nulll; //定义一个文件流 fileStream=new FileStream("profile.bin",FileMode.Create); //二进制方式 BinaryFormatter bf=new BinaryFormatter(); Profile=(Profile)bf.Deserialize(fileStream); } e.序列化与反序列化的用途 (1)将数据保存在磁盘中,并在以后检索此数据,将数据还原为属性和字段。 (2)将一个应用程序的东西发布到另一个应用程序。 在三层中体现出来 (3)在远程通信中应用非常广泛,可以将一个应用程序中的对象序列化,然后通过网络通信,远程传递给其他地点的另一个应用程序 例如:WebService开发 9-2:程序集与反射 a.什么是程序集 编译好的.exe文件,称为程序集。程序集是.NET框架应用程序的生成块,它包含编译好的代码逻辑单元。 b.程序集的结构 (1)程序集清单 (2)元数据 (3)其他内容 c.查看程序集 d.程序集中的访问修饰符 类内部 同一程序集的工、派生类 同一程序集的其他子类 不同程序集的派生类 不同程序集的其他类 private 可以 不可以 不可以 不可以 不可以 protected 可以 可以 不可以 可以 不可以 internal 可以 可以 可以 不可以 不可以 public 可以 可以 可以 可以 可以 e.反射 导入 System.Refection.Assembly; 例如: class Program { static void Main() { string version=Assembly.LoadFile("D:\MyNewsReader.exe"); Console.WriteLine(version); } }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

awk学习笔记

awk是一种模式扫描和处理工具,相对于grep的查找,sed的编辑,它在对数据进行分析生成报表时显得尤为强大。awk通过逐行遍历一个或多个 文件的方式,查找模...

31760
来自专栏向治洪

ES7和ES8新特性介绍

概述 JavaScript,作为一门处于高速发展期的开发语言,正在变的越来越完善、稳定。我们必须拥抱这些变化,并且我们需要把ES8加入到我们的技术栈中。 ECM...

73860
来自专栏腾讯IVWEB团队的专栏

踩坑记:当 JavaScript 遇上 UINT 64

写下这篇文章的缘由是因为在项目过程中,碰到了一个使用 JavaScript 处理 UINT64 类型数字的坑。二进制浮点数中的 0.1 和 0.2 并不是十分...

84200
来自专栏Golang语言社区

动手实现一个JSON验证器(上)

分析 既然要验证JSON的有效性,那么必然需要清楚的知道JSON格式,这个在JSON官网已经给我们画出来了: ? ? ? ? ? 从官方的图上面可以看出,JSO...

54970
来自专栏Java Web

Java 面试知识点解析(四)——版本特性篇

16350
来自专栏進无尽的文章

编码篇-低耦合代码注入

我下面要将的内容也许网上已经有很多相关的介绍了,但是我还是会写出这篇文章,一来是对自己学习的总结,虽然总结的有些晚,如果你仔细看,会发现我的文章有别处没有的内容...

12120
来自专栏静晴轩

lua表排序

Lua作为一种很强大且轻量级脚本语言的存在,对于掌握其几乎无所不能的Table(其实就是一个Key Value的数据结构,它很像Javascript中的Obje...

555110
来自专栏逍遥剑客的游戏开发

C++的反射和序列化

20420
来自专栏贾老师の博客

Boost 中的智能指针

10820
来自专栏Taylor技术日志

关于char/varchar(n)中n的探究:字符数or字节数

很多时候我们不确定某个字段的长度,会使用varchar类型,比如某个字段定义为varchar(100),那这100的长度能存多少个中文?

47770

扫码关注云+社区

领取腾讯云代金券