.NET框架运行在操作系统之上,是.NET最基础的框架,它提供了创建、部署和运行.NET应用的环境,主要包含公共语言运行时(CLR)和框架类库(.NET Framework类库,FCL),并且支持多种开发语言。
CLR的全称是公共语言运行时(Common Language Runtime),它是所有.NET应用程序运行时环境,是所有.NET应用程序都要使用的编程基础。CLR包含两个组成部分:CLS(公共语言规范)和CTS(通用类型系统)。
CTS通用类型系统(Common Type System)用于解决不同语言数据类型不同的问题。
CLS公共语言规范(Common Language Specification)限制了由这些不同点引发的互操作性问题,是一种最低的语言标准。
FCL是.NET框架的一个重要部分,即框架类库。在.NET框架中提供了非常丰富实用的类库,这些类库都是我们进行软件开发的利器例如
System; //此命名空间包含所有其他的命名空间
System.Collections.Generic;//支持泛型操作
System.IO;//支持对文件的操作
System.Net;//支持对网络协议的编程
System.Data;//提供对表示ADO.NET结构的类的访问
System.Windows.Forms;//用于开发Windows应用程序
System.Drawing;//支持GDI+基本图形操作
以上都是一些.NET框架的核心类库及其2功能。
我们都知道关于类和对象之间的关系:
对于类的属性,我们通过get和set访问器进行访问和设置,用来保障类中数据的安全,如:
封装被称为信息隐藏,是指利用抽象数据类型将数据和数据的操作结合在一起,使其构成一个不可分割的独立实体,尽可能隐藏内部的细节,只保留一些对外接口,使之与外部发生联系。
封装主要给我们带来了如下好处:
将字段封装为属性是封装的一种方式,类的私有方法也是一种封装。
常用的数据类型:
常用数据类型 | Java | C# |
---|---|---|
整型 | int | int |
浮点型 | float | float |
双精度型 | double | double |
字符串 | String | string |
布尔型 | boolean | bool |
枚举型 | menu | menu |
值类型源于System.ValueType家族,每个值类型的对象都有一个独立的内存区域用于保存自己的值,值类型数据所在的内存区域称为栈(Stack)。
引用类型源于System.Object家族,在C#中引用类型主要包括数组、类和接口等。
注意:值类型的值保存在栈中,一旦在代码中修改它的值,它保存在栈中的值都会发生改变。引用类型的值保存在堆中,同时会在栈中保存堆的地址,是指向性的,在修改同一个堆中的值时,才会改变。
当发现一个类中具有的字段都是值类型的,而且个数比较少,此时我们可以用C#为我们提供的结构(Structure)这个数据类型。
结构的定义:
访问修饰符 struct 结构名
{
//结构体
}
注意:结构中可以有字段,也可以有方法。定义时,结构中的字段不能被赋初值。不能手写构造函数,定义构造函数时有多少字段就要有多少个参数,为字段赋值。
关于结构的使用:
注意:
装箱:将值类型转换为引用类型的过程
拆箱:将引用类型转换为值类型的过程
注意:在拆箱时,被转换引用类型的数值必须能够转换为目标值类型。其次在实际的开发中,应该尽量减少不必要的装箱和拆箱,因为二者的存储方式不同,转换时性能损失较大。
在C#中传递分为:1.值传递 2.引用传递
数组是一组具有相同类型的数据的集合,但是数组的大小是固定的。从此我们可以想到是否能建立一个动态的“数组”,有了集合。
ArrayList非常类似于数组,也有人称它为数组列表,ArrayList可以动态维护。
ArrayList类属于System.Collections命名空间,这个命名空间包含接口和类,这些接口和类定义各种对象的集合。
注意:ArrayList是动态可维护的,因此定义时即可以指定容量,也可以不指定容量。
定义:
using System.Collections;//使用前必须导入System.Collections命名空间
//创建容量为0的ArrayList对象
ArrayList students = new ArrayList();
//创建容量为5的ArrayList对象
ArryaList students = new ArrayList(5);
ArrayList的常用方法及属性
属性名称 | 说明 |
---|---|
Count | 获取ArrayList中实际包含的元素数 |
方法名称 | 说明 |
int Add(Object value) | 将对象添加到ArrayList的结尾处 |
void RemoveAt(int index) | 移除ArrayList指定索引处的元素 |
void Remove(Object value) | 从ArrayList中移除特定对象 |
void Clear() | 从ArrayList中移除所有元素 |
ArrayList获取一个元素的方法和数组是一样的,也是通过索引(index)来访问,ArrayList中的第一个元素索引是0。
注意:由于给ArrayList添加的元素都会被转换为Object型,所以在访问这些元素时必须把它们转化回原来的数据类型。
在遍历ArrayList中的元素,我们可以通过for循环和foreach循环,因为它是通过索引访问的。
//SE为自定义类
//for循环遍历
for(int i = 0; i < engineers.Count; i++)
{
SE seFor = (SE)engineers[i];
Console.WriteLine(seFor.Name);
}
//foreach循环遍历
foreach(Object obj in engineers)
{
SE seForeach = (SE)obj;
Console.WriteLine(seForeach.Name);
}
删除元素:ArrayList在添加和删除元素时都会使剩余元素的索引自动改变,Remove()方法和RemoverAt()方法只能删除一个元素。Clear()方法可以删除集合中的所有元素。
C#中提供了一种称为Hashtable的数据结构,通常称为哈希表,也有人称它为“字典”。Hashtable的数据是通过键(Key)和值(Value)来组织的。
Hashtable也属于System.Collections命名空间,它的每个元素都是一个键/值对。
Hashtable的常用方法及属性
属性名称 | 说明 |
---|---|
Count | 获取包含在Hashtable中键/值对的数目 |
Keys | 获取包含在Hasbtable中的键的集合 |
Values | 获取包含在Hashtable中值的集合 |
方法名称 | 说明 |
void Add(Object key,Object value) | 将带有指定键和值的元素添加到Hashtable中 |
void Remove(Object key) | 从Hashtable中移除带有特定键的元素 |
void Clear() | 从Hashtable中移除所有元素 |
注意:Hashtable的Add()方法有两个参数,一个表示键,一个表示键所对应的值。
获取Hashtable的元素和ArrList不同,访问Hashtable元素时可以直接通过键名来获取具体值。同样,由于值的类型是Object,所有得到一个值是也需要通过类型转换得到指定类型的对象。
删除Hashtable的元素通过键(Key),使用Remove()方法删除。
遍历Hashtable的元素,因为Hashtable不能用索引访问,所以遍历Hashtable只能用foreach()方法。
Hashtable a = new Hashtable();
//遍历key
foreach(Object obj in engineers.Keys)
{
Console.WriteLine((string)obj);
}
//遍历value
foreach(Object obj in engineers.Values)
{
SE se = (SE)obj;
Console.WriteLine(se.Name);
}
注意:以上代码是分别对engineers.Keys和engineers.Values遍历,而不是对engineers对象本身。
泛型是C#2.0中的一个新特性。泛型引入了一个概念:类型参数。通过使用类型参数(T)减少了运行时强制转换或装箱操作的风险,通过泛型可以最大限度地重用22代码、保护类型的安全及提高性能,它的最常见应用就是创建集合类,可以约束集合类中的元素类型。比较典型的泛型集合是List
定义:
List 对象名 = new List();
注意:“
List
List
异同点 | List |
ArrayList |
---|---|---|
不同点 | 对所保存元素进行类型约束 | 可以增加任何类型 |
添加/读取值类型元素无须拆箱、装箱 | 添加/读取值类型元素需要拆箱、装箱 | |
相同点 | 通过索引访问集合中的元素 | |
添加元素方法相同 | ||
删除元素方法相同 |
在C#中还有一种泛型集合Dictionary
Dictionary 对象名 = new Dictionary();
注意:
Dictionary
Dictionary
异同点 | Dictionary |
Hashtable |
---|---|---|
不同点 | 对所保存元素进行类型约束 | 可以增加任何类型 |
添加/读取值类型元素无须拆箱、装箱 | 添加/读取值类型元素需要拆箱、装箱 | |
相同点 | 通过Key获取Value | |
添加元素方法相同 | ||
删除元素方法相同 | ||
遍历方法相同 |
在集合中使用泛型只是泛型多种应用的一种,在类、方法等方面也有着泛型的广泛应用,使用泛型类,可以封装不是特定于具体数据类型的操作。
对于一些常常处理不同类型数据转换的类,可以使用泛型定义。
定义语法:
public class 类名
{
//......
}
注意:T指类型参数,代表具体的数据类型,可以是类类型,也可以是基本数据类型。
泛型的优点:
构造函数是一种创建类实例的方法,是类中的一种特殊方法。
特点及作用:
在默认的情况下,系统将会给类分配一个无参构造函数,并且没有方法体,当然我们也可以自己定义一个无参方法。定义语法:
访问修饰符 类名()
{
//方法体
}
无参构造函数给成员变量赋值有一个缺点,就是属性值是固定的,为了满足对象多样化需求,我们就有了有参的构造函数。定义语法:
访问修改符 类名(参数列表)
{
//方法体
}
参数列表一般用来给类的属性赋值。
注意:在类中,一旦自定义了构造函数,那么这个类的隐藏的默认无参构成函数就会消失,所以,我们一般都会自定义一个无参构造函数。
多个构造函数提供了多种实例化一个类的方式,这种方式就是方法的重载;重载是多态的一种实现方式。在面向对象的语言中,允许我们在同一个类中定义多个方法名相同、参数列表(参数个数、参数类型)不同的方法,称为方法重载。
特点:
注意:方法名及参数列表相同的方法,仅是返回值类型不同,不能称为方法重载。
在之前我们也介绍过类的三大特性:封装、继承、多态,封装之前已经介绍过了,下面我们来介绍一下继承和多态。
子承父:指一个类可以继承另一个类,子类拥有父类所有非 private 成员,还可以拥有自己独有的成员。在继承过程中,被继承的类被称为父类或基类,继承的类被称为子类或派生类,如:
public class Employee
{
public Employe(){}
//工号
protected string ID { get; set; }
//年龄
protected int Age { get; set; }
//姓名
protected string Name { get; set; }
}
public class PM:Employee
{
public PM(){}
public int YearOfExperience { get => _yearOfExperience; set => _yearOfExperience = value; }//人气值
public PM(string id, string name,int age,int yearOfExperience)
{
this.ID = id;
this.Name = name;
this.Age = age;
this.YearOfExperience = yearOfExperience;
}
}
注意:protected,受保护的,是一种访问修饰符,关于修饰符的区别如下:
修饰符 | 类内部 | 子类 | 其他类 |
---|---|---|---|
public | 可以 | 可以 | 可以 |
protected | 可以 | 可以 | 不可以 |
private | 可以 | 不可以 | 不可以 |
从表格中可以看出,三中访问修饰符对类成员的访问限制强度:private > protected > public。
注意:在类中 this 表是当前类的对象的引用,在子类中 base 表示调用父类的成员。
当一个子类继承父类后,在调用子类构造函数时,会自动调用父类的构造函数,这种调用也分为隐式和显式调用。
隐式:在子类中没有指明要调用父类的哪一个构造函数,那么系统会隐式地调用父类的无参构造函数。
显式:C#中可以使用base关键字调用父类的构造函数,只要在子类的构造函数后添加":base(参数列表)",就可以指定该子类的构造函数调用父类的哪一个构造函数了。
注意:base关键字调用父类传递的参数列表是没有带数据类型的,只能传递参数。
继承的传递性:继承需要符合 is a 的关系,例如:“小型卡车 is a 卡车,卡车 is a 汽车,小型卡车 is a 汽车”,就是小型卡车继承卡车,卡车继承汽车,那么小型卡车继承汽车,这就是继承的传递性
继承的单根性:在C#中一个子类不能同时继承多个父类,只能继承一个父类。
注意:在C#中有一个关键字 sealed,用来修饰类,用它修饰的类是不能被继承的,我们称这中类为密封类。如常用的 string 类就是密封类。
如果有两个类继承自一个类,如“A继承C,B继承C”那么我们可以定义一个" List
SE ai = new SE("112","艾边成",25,100);
SE joe = new SE("113","Joe",30,200);
PM pm = new PM("890","盖茨",50,30);
List<Employee> empls = new List<Employee>();
empls.Add(ai);
empls.Add(joe);
empls.Add(pm);
foreach (Employee empl in empls)
{
if (empl is SE)
{
Console.WriteLine(((SE)empl).SayHi());
}
if (empl is PM)
{
Console.WriteLine(((PM)empl).SayHi());
}
}
is 关键字:这个关键字用来判断对象是否属于给定的类型,如果属于返回 true ,否则返回false;
as关键字:用来强制转换数据类型,如:对象名 as 数据类型
关于继承的特点:
如果父类的子类非常多,子类的方法各个不同时,那么在程序中就要对众多的对象编写非常多的if语句进行判断,使程序变得庞大,扩展困难,这里就介绍一种虚方法
//修改父类的方法
public virtual string SayHi()
{
//省略方法体
}
//修改子类的方法
public override string SayHi()
{
//省略方法体
}
SE ai = new SE("112","艾边成",25,100);
SE joe = new SE("113","Joe",30,200);
PM pm = new PM("890","盖茨",50,30);
List<Employee> empls = new List<Employee>();
empls.Add(ai);
empls.Add(joe);
empls.Add(pm);
foreach (Employee empl in empls)
{
Console.WriteLine(empl.SayHi());
}
虚方法中父类用 virtual 关键字来声明,子类中用 override关键字修饰的方法称为方法的重写,虚方法可以被重写的,方法的重写是实现多态的一种形式。
继承的优缺点
优点:
缺点:
多态是指一种事物的多种形态,按字面意思就是多种形态,指同一操作作用于不同的对象时,可以有不同的解释,产生不同的执行结果。
在C#中我们怎么实现多态:
方法的重载前面已经说到过了,现在说一下方法的重写
重写的前提是两个类之间必须存在继承关系,子类重写父类的方法。
重写在C#中也分为两种重写的方法:
重写的特点:
注意:
定义语法:
访问修饰符 abstract 返回值类型 方法名();
注意:抽象方法必须定义在抽象类中,在抽象方法中是不能有方法体的
存在的意义:规定子类必须重写父类的抽象方法
定义抽象类语法
访问修饰符 abstract class 类名
{
}
特点:
注意:每个类都一定有一个父类,没有显示定义,那么类的父类就是Object
在面向对象的编程中是低耦合,高内聚的。
有5大设计原则,可以百度查看一下。‘
好的谢谢观看。