一-七章总结
一、深入.NET框架
1、.NET框架体系结构
1、.NET框架结构
.NET框架运行在操作系统之上,是.NET最基础的框架。它提供了创建、部署和运行。.NET应用的环境,主要包含公共语言运行(CLR)和框架类库(.NET Framework 类库 FCL),并且支持多种开发语言。
.NET框架具有两个主要组件:CLR和FCL是.NET框架的基础。FCL是一个综合性的面向对象的可重用的类型集合,利用他不仅可以开发传统命令行应用程序,而且可以开发WinForms应用程序及基于ASP.NET的应用程序。
1.CLR
CLR的全称为公共语言运行时。它是所有.NET应用程序运行时环境,是所有.NET应用程序都要使用的程序基础,它如同一个支持.NET应用程序运行和开发的虚拟机。CLR包含两个组成部分:CLS(公共语言规范)和CTS(通用类型系统)。
(1)CTS
C#和VB.NET都是CLR的托管代码,它们的语法和数据类型各不相同。通用类型系统用于解决不同语言数据类型不同的问题。
(2)CLS
编程语言的区别不仅在于类型、语法或者语言规范也都有很大的区别。因此.NET通过定义公共语言规范,限制了由这些不同点引发的互操作性问题。
2.FCL
.NET框架另外一个重要部分是FCL,即框架类库。
3…NET框架的核心类库及其功能
System:此命名空间包含所有其他的命名空间。
System.Collections.Generic:支持泛型操作。
System.lo:支持对文件的操作,如复制,粘贴,删除及对文件的读写等。
System.NET:支持对网络协议的编程。
System.Data:提供对表示ADO.NET结构的类的访问。
System.Windows.Forms:用于开发Windows用于程序。
System.Drawing:支持CDI+基本图形操作。
2、面向对象回顾
1、类和对象
类和对象有着本质的区别,类定义了一组概念的模型,而对象是真实地实体,它们之间的关系如下
1.由对象归纳为类,是归纳对象共性的过程。
2.在类的基础上,将状态和行为实体化为对象的过程称为实例化。
对于类的属性,我们通过get和set访问器进行访问和设置,用来保障类中数据的安全。属性访问器分为以下三种;
1.只读属性:只包含get访问器。
2.只写属性:只包含set访问器。
3.读写属性:同时包含set访问器和get访问器。
2、封装
封装主要给我们带来如下好处:
1.保证数据的安全性。
2.提供清晰的对外接口。
3.类内部实现可以任意修改,不影响其他类。
3、类图
类图是表示类的结构及类与类之间关系的图表。
二、深入.NET平台和C#编程
1、值类型和引用类型
1、概述
C#为了提高开发效率,与Java提供的数据类型非常相似。C#中最常用的数据类型,如下表中所示
常用数据类型 | Java | C# | 举例 |
---|---|---|---|
整型 | int | int | 年龄 |
浮点型 | float | float | 成绩 |
双精度型 | double | double | 圆周率 |
字符串 | String | string | 家庭住址 |
布尔型 | boolean | bool | 是否为少数名族 |
枚举类型 | enum | enum | 颜色 |
1.值类型
值类型源于System.ValueType家族,每个值类型的对象都有一个独立的内存区域用于保存自己的值,值类型数据所在的内存区域称为栈。只要在代码中修改它,就会在它的内存区域内保存这个值。
2.引用类型
引用类型源于System.Object家族,在C#中引用类型主要包括数组、类和接口等。
3.细分值类型和引用类型
int类型是值类型,数组是引用类型。C#中包含的值类型和引用类型。
2、结构
1.结构的定义
语法
访问修饰符 struct 结构名
{
//结构体
}
结构的定义有以下特点:
(1)结构中可以有字段,也可以有方法。
(2)定义时,结构中的字段不能被赋初值。
2.结构的使用
结构的构成和类相似。在使用结构时,要注意以下几个方面。
(1)可以不用new,直接定义的对象即可。
(2)声明结构的对象后,必须给结构的成员赋初值。
3.结构的使用经验
结构是值类型,声明结构变量就存储一个结构的新副本,即系统要开辟一块新的空间,因此结构用的越多所消耗的存储空间也就越多。
3、装箱和拆箱
数据类型按照存储方式可以分为值类型和引用类型,两者仍然可以相互转换。将值类型转换为引用类型的过程称为装箱,反之称为拆箱。
2、不同类型的参数传递
1、概述
为方法传递参数,我们以前学了值传递和ref方式传递两种参数传递方式。
(1)使用值传递,在方法中对参数值的更改在调用后不能保留。
(2)使用ref方式传递,可以保留对参数值的更改。
2、值方法参数传递
在值方法参数传递时,参数可以是引用类型,也可以是值类型。
3、引用方式参数传递
在引用方式参数传递时,参数同样可以是引用类型,也可以是值类型。
小结:
1.使用值方式(不用ref修饰)传递值类型参数时,参数在方法中的修改不会保留。
2.使用值方式(不用ref修饰)传递引用类型参数时,参数在方法中的修改会保留。
3.使用值方式(不用ref修饰)传递值类型和引用类型参数时,参数在方法中的修改都会保留。
三、使用集合组织相关数据
1、集合概述
1、ArrayList
ArrayList非常类似于数组,也有人称它为数组列表,ArrayList可以动态维护。
ArrayList类属于System.Collections命名空间,这个命名空间包含接口和类,这些接口和类定义各种对象(如:列表、队列、为数组、哈希表和字典)的集合。ArrayList就属于集合的一种,因此,在使用ArrayList类之前一定要引入System.Collections命名空间。
ArrayList的常用方法及属性如下;
属性名称 | ||
---|---|---|
Count | 获取ArrayList中实际包含的元素数 | |
返回值类型 | 方法名称 | 说明 |
int | Add(Object value) | 将对象添加到ArrayList的结尾处 |
void | RemoveAt(int index) | 移除ArrayList指定索引处的元素 |
void | Remove(Object value) | 从ArrayList中移除特定对象 |
void | Clear() | 从ArrayList中移除所有元素 |
1.给ArrayList添加数据
通过Add()方法可将对象添加到ArrayList的结尾处。该方法说明如下:
(1)返回值:值是一个int整数,用于返回所添加的元素的索引。
(2)参数:如果向ArrayList中添加的元素是值类型,这些元素就会装箱处理为Object引用类型,然后保存,因此,ArrayList中的所有元素都是对象的引用。
2.存取ArrayList中的单个元素
ArrayList获取一个元素的方法和数组是一样的,也是通过索引(index)来访问,ArrayList中第一个元素的索引是0。需要注意的是,由于给ArrayList添加的元素都会被装换为Object型,所有在访问这些元素的元素的时候必须把它们转换会原来的数据类型。
3.遍历ArrayList中的元素
在数组中,我们可以通过循环的方式将元素逐个取出。这种操作方法通常称为遍历元素,以数组的长度作为循环次数,将循环变量作为数组的索引,逐个取出元素,例如:
static void Main(string[] args)
{
int[] array=new int[]{0,1,2,3,4}
for(int i=0;i<array.Length;i++)
{
Console.WriteLine(array[i]);
}
}
ArrayList也可以用这样的方法遍历,因为它也是通过索引访问的。
2、Hashtable
Hashtable也属于System.Collections命名空间,它的每个元素都是一个键/值对。
Hashtable的常用方法及属性,如表所示:
属性名称 | 说明 | |
---|---|---|
Count | 获取包含在Hashtable中键/值对的数目 | |
Keys | 获取包含在Hashtable中键的集合 | |
Values | 获取包含在Hashtable中值的集合 | |
返回值类型 | 方法名称 | 说明 |
void | Add(Object key,Object value) | 将带有指定键和值的元素添加到Hashtable中 |
void | Remove(Object key) | 从Hashtable中移除带有特定键的元素 |
void | Clear() | 从Hashtable中移除所有元素 |
1.Hashtable通过Add()方法添加元素
Hashtable的Add()方法有两个参数,一个表示键,一个表示键所对应的值。
2.获取Hashtable的元素
和ArrayList不同,访问Hashtable元素时可以直接通过键名来获取具体值。同样,由于值的类型是Object,所以当得到一个值时也需要通过类型转换得到指定类型的对象。
3.删除Hashtable的元素
通过键(Key),使用Remove()方法就可以删除Hashtable的元素。
4.遍历Hashtable中的元素
由于Hashtable不能用索引访问,所以遍历一个Hashtable只能用foreach()方法。
2、泛型和泛型集合
1、泛型
泛型引入了一个概念:类型参数。通过使用类型参数(T),减少了运行时强制转换或装箱操作的风险,通过泛型可以最大限度地重用代码、保护类型的安全及提高性能,它的最常见应用就是创建集合类,可以约束集合类中元素类型。比较典型的泛型集合是List和Dictionary<K,V>.
2、泛型集合List
在System.Collections.Generic命名空间中定义了许多泛型集合类,这些类可以代替ArrayList和Hashtable。
定义一个List泛型集合的方法如下。
List<T> 对象名=new List<T>();
""中的T可以对集合中的元素类型进行约束,T表明集合中管理的元素类型。
List与ArrayList的区别
异同点 | List | ArrayList |
---|---|---|
不同点 | 对所保存元素进行类型约束 | 可以增加如何类型 |
添加/读取值类型元素无须拆箱、装箱 | 添加/读取值类型元素需要拆箱、装箱 | |
相同点 | 通过索引访问集合中的元素 | 通过索引访问集合中的元素 |
添加元素方法相同 | 添加元素方法相同 | |
删除元素方法相同 | 删除元素方法相同 |
3、泛型集合Dictionary<K,V>
在C#中还有一种泛型集合Dictionary<K,V>,它具有泛型的全部特性,编译时检查类型约束;获取元素时无须类型转换,并且它存储数据的方法和Hashtable类似,也是通过Key/Value(键/值)对元素保存的。
定义一个Dictionary<K,V>泛型集合的语法如下。
Dictionary<K,V> 对象名=new Dictionary<K,V>();
说明:<K,V>中的K表示集合中Key的类型,V表示Value的类型。它们的含义和List是相同的。
Dictionary<K,V>和Hashtable的对比
异同点 | Dictionary<K,V> | Hashtable |
---|---|---|
不同点 | 对所保存元素进行类型约束 | 可以增加如何类型 |
添加/读取值类型元素无须拆箱、装箱 | 添加/读取值类型元素需要拆箱、装箱 | |
相同点 | 通过Key获取Value | 通过Key获取Value |
添加元素方法相同 | 添加元素方法相同 | |
删除元素方法相同 | 删除元素方法相同 | |
遍历方法相同 | 遍历方法相同 |
4、泛型类
在集合中使用泛型只是泛型多种应用的一种,在类、方法等方面也有着泛型的广泛应用。使用泛型类,可以封装不是特定于具体数据类型的操作。
泛型类的定义如下:
public class 类名<T>
{
//···
}
T指类型参数,代表具体的数据类型,可以是类类型,也可以是基本数据类型。
四、深入类的方法
1、构造函数
1.构造函数
类的构造函数是类中的一种特殊方法,它具有以下特点。
方法名与类名相同;没有返回值类型;主要完成对象的初始化工作。
2.无参构造函数
默认的情况下,系统将会给类分配一个无参构造函数,并且没有方法体。在我们也可以自定义一个无参构造函数,在无参构造函数的方法体中对类的属性进行赋值。无参构造函数的语法如下。
访问修饰符 类名()
{
//方法体
}
3.带参构造函数
访问修饰符 类名(参数列表)
{
//方法体
}
参数列表一般用来给类的属性赋值。
2、方法重载
1、构造函数的重载
方法重载的特点:
方法名相同;方法参数类型不同或者参数个数不同;在同一个类中。
3、对象交互
在面向对象的世界里,一切皆为对象。对象与对象相互独立,互不干涉,但在一定外力的作用下,对象开始共同努力。
六、初始继承和多态
1、继承概述
1、什么是继承
被继承的类称为父类或者基类;继承其他类的类称为子类或者派生类。
2、base关键字和protected修饰符
关键字base,它表示父类,可以用于访问父类的成员。父类中的成员如果用private修饰,它将作为私有成员,其他任何类都无法访问。如果设置为公有(public)成员,任何类都可以访问该成员,这不符合我们的要求。C#中提供了另一种访问修饰符protected,被这个访问修饰符的成员允许被其子类访问。
public、protected和private这三修饰符的区别如下表所示
修饰符 | 类内部 | 子类 | 其他类 |
---|---|---|---|
public | 可以 | 可以 | 可以 |
protected | 可以 | 可以 | 不可以 |
private | 可以 | 不可以 | 不可以 |
3、子类构造函数
1.隐式调用父类构造函数
创建子类对象时会首先调用父类的构造函数,然后才会调用子类本身的构造函数。由于没有指明要调用父类的哪一个构造函数,所以系统隐式地调用了父类的无参构造函数。
2.显示调用父类构造函数
C#可以用base关键字调用父类的构造函数。只要在子类的构造函数后添加“:base(参数列表)”,就可以指定该子类的构造函数调用父类的哪一个构造函数了。
2、继承的使用
1、继承的特征
继承具有传递性:如果class A:B,class B:A,A也可以访问C的成员。
继承的单根性:在C#中明确规定,一个子类不能同时继承多个父类。
2、is a 的应用
is a:判断真正的数据类型
语法:引用名[对象名] is 数据类型
3、继承的价值
1.继承模拟了现实世界的关系,OOP中强调一切皆对象,这符合我们面向对象编程的思考方向。
2.继承实现了代码的重用,合理地使用继承,会使代码更加简洁。
3.继承使得程序结构清晰,子类和父类的层次结构清晰,最终的目的是使子类只关注子类的相关行为和状态,无须关注父类的行为和状态。
3、多态
使用virtual关键字修饰的方法,称为虚方法。虚方法有方法体。语法如下。
访问修饰符 virtual 返回类型 方法名()
{
//方法体
}
通过override关键字来修饰的方法,称为方法的重写。虚方法可以被重写。方法重写语法如下。
访问修饰符 override 返回类型 方法名()
{
//方法体
}
1、实现多态
实现方法重写
1.父类中定义SayHi()方法,用virtual关键字定义为虚方法。
2.在子类中定义子类自己的SayHi()方法,用override关键字修饰,就实现了对父类SayHi()方法的重写。
七、深入理解多态
1、里氏替换和多态应用
1、里氏替换概述
1.里氏替换原则的应用
里氏替换原则是软件设计应该遵守的重要原则之一。有了里氏替换原则,才使继承复用成为可能,只有当子类可以替换父类时,软件的功能不受影响,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
2.is和as操作符的使用
is操作符用于检查对象和指定的类型是否兼容。
as操作符主要用于两个对象之间的类型转换。
2、父类类型作为参数
里氏替换原则指出子类对象可以代替父类对象,那么在开发程序时可以编写以父类类型作为形式参数的方法,在实际调用时传入子类对象,从而实现多态。
2、抽象类和抽象方法
1、为什么使用抽象类和抽象方法
C#中用抽象类和抽象方法来解决这个问题
抽象方法是一个没有实现的方法,通过在定义方法是增加关键字abstract可以声明抽象方法,其语法如下
访问修饰符 abstract 返回类型 方法名();
注意,抽象方法没有关闭的大括号,而是直接跟了一个分号“;”,也就是说,它没有包括方法执行逻辑的方法体。
含有抽象方法的类必然是抽象类。同样,我们用abstract关键字来定义一个抽象类,其语法如下
访问修饰符 abstract class 类名{}
2、抽象类和抽象方法的应用
当从一个抽象父类派生一个子类时,子类将继承父类的所有特征,包括它为实现的抽象方法。抽象方法必须在其子类中实现,除非它的子类也是抽象类。与子类重写父类的虚方法一样,在子类中也是使用override关键字来重写抽象方法的。
访问修饰符 override 返回类型 方法名()
虚方法和抽象方法的区别如表所示:
虚方法 | 抽象方法 |
---|---|
用virtual修饰 | 用abstract修饰 |
要有方法体,即使是一个分号 | 不允许有方法体 |
可以被子类override | 必须被子类override |
除了密封类外都可以定义 | 只能在抽象类中定义 |
3、面向对象的三大特性
封装:保证对象自身数据的完整性和安全性
继承:建立类之间的关系,实现代码复用,方便系统的扩展
多态:相同的方法调用可实现不同的实现方式