深入.NET框架和C#编程(一)

本文深入解析了.NET框架的结构,包括公共语言运行时(CLR)和框架类库(FCL)的细节,以及C#中的面向对象编程概念。涵盖了数据类型、集合、类的方法、继承和多态等核心主题。

深入.NET框架和C#编程

一.深入.NET框架

1.1NET框架的体系结构

NET框架结构:

.NET框架运行在操作系统之上,是.NET最基础的框架,主要包含公共语言运行时(CLR)和框架类库(FCL)。

(1)公共语言运行时(CLR):

它是所有.NET应用程序运行时的环境,是所有.NET应用程序都要使用的编程基础,它如同一个支持.NET应用程序运行和开发的虚拟机。

MSIL:俗称中间语言,可被平台(操作系统)识别,从而进行编译

CLR包含两个组成部分:

  1. CLS(公共语言规范)
  2. CTS(通用类型系统)

CLS:编程语言区别不仅在于类型,语法或者语言规范都有很大的区别,CLS限制了不同点引发的互操性问题。

CTS:用来解决不同语言数据类型的不同的问题;

(2)框架类库(FCL)

就是指平常要引用的那些命名空间,.NET框架提供了非常丰富实用的类库。

1.2.面向对象回顾

1.2.1类和对象

类和对象有着本质的区别,类定义了一组概念的模型(抽象的),而对象是真正的实体。

①由对象归纳为类,是归纳对象共性的过程。

②在类的基础上,将状态和行为实体化为对象的过程称为实例化。

属性:

  1. 只写属性:只包含set访问器
  2. 只读属性:只包含get访问器
  3. 读写属性:同时包含set访问器和get访问器
private  int _id;
public int ID
{
    get {return_id;}
	set {_id=value;}
}
1.2.2封装

封装:使内部结构私有化

封装的魅力:

  • 保证数据的安全性
  • 提供清晰的对外接口
  • 类内部实现可以任意修改,不影响其他类

将字段封装为属性是封装的一种方式,类的私有方法也是一种封装。

1.2.3类图

在软件开发中,软件的规模一般都很大,一行行阅读是非常困难的,在面向对象编程中,我们经常使用类图来解决这个问题。类图将类的属性和行为以图的行为展示出来,使读者不用阅读大量的代码就可以知道类的功能及类之间的关系。

私有成员: “-”,公有成员:“+”;也有私有成员在右下角有“”标志

类图是表示类的结构及类与类之间关系的图表。

二.深入C#数据类型

1.值类型和引用类型

1.值类型

值类型源于System.ValueType命名空间,值类型数据所在的区域称为 “栈”,只要修改它,就会在它的内存区域内保存这个值,值类型主要包括的基本数据类型 :

int, long, float, double, char, bool, bool,enum, struct

2.引用类型

引用类型源于System.Object命名空间,在C#中引用类型主要包括 :

类(Class),数组,集合,接口

2.1 结构

1,结构的语法

访问修饰符  struct  结构名
{
      //结构体
}

2,结构的定义有以下的特点:

  • 结构中可以有字段,也可以有方法;
  • 定义时,结构中的字段不能被赋初始值;

3,在使用结构时要注意以下几个方面:

  • 可以不用new,直接定义结构的对象即可;
  • 声明结构后,必须给结构的成员赋初值;
1.1装箱和拆箱

我们说数据类型按照储存方式可以分为值类型和引用类型,两者可以互相转换。

  • 装箱:将值类型转换为引用类型的过程叫装箱。
  • 拆箱:将引用类型转换为值类型叫拆箱。
static void Main(string [] args)

{

  int i=123; 
//装箱
object o=i;  
//拆箱
int j=(int)o;  

}

2.参数传递

  1. 值传递:在方法中对参数值的更改在调用后不能保留;
  2. 引用传递:地址不变,可以保留对参数值的更改
  3. 使用ref传递:可以保留对参数值的更改;

总结

  1. 使用值方式(不用ref修饰)传递值类型参数时,参数在方法中的修改不会保留;
  2. 使用值方式(不用ref修饰)传递引用类型参数时,参数在方法中的修改会保留;
  3. 使用引用方式(用ref修饰)传递值类型或引用类型参数时,参数在方法中的修改都会保留;

三.使用集合组织相关数据

1.非泛型

1.1.ArrayList

ArrayList非常类似于数组,也有人称它为数组列表,ArrayList可以动态维护,一般数组的长度都是固定的,而ArrayList的容量可以根据需要自动扩充,它的索引会根据程序的扩展而重新分配调整.

ArrayList类属于System.Collections命名空间,这个命名空间包含接口和类;

ArrayList常用的方法和属性:

属性名称说明
Count获取ArrayList中实际包含的元素数
返回值类型方法名称说明
intAdd(Object value)将对象添加到ArrayList的结尾处
voidRemoveAt(int index)移除ArrayList指定的索引元素
voidRemove(Object value)从ArrayList中移除特定元素
voidClear()移除所有元素

遍历ArrayList中的元素

ArrayList array = new ArrayList();

foreach(Object item in array)
{
    Console.WirteLine(item);
}
1.2.Hashtable

C#提供了一种称为Hashtable的数据结构,通常称为哈希表,Hashtable的结构是通过键(Key)和值(Value)来组织的

Hashtable也属于System.Collections命名空间,它的每一个元素都是一个键/值对;

Hashtable的常用属性和方法:

属性名称说明
Count获取包含Hashtable中键/值对的数目
Keys获取包含在Hashtable中键的集合
Values获取包含在Hashtable中值的集合
返回值类型方法名称说明
voidAdd(Object key,Object value)带有指定键和值的元素添加到Hashtable
voidRemove(Object key)从Hashtable中移除带有特定键的元素
voidClear()从Hashtable中移除所有元素

遍历Hashtable中的元素

Hashtable<K,V> array = new Hashtable<K,V>();
//遍历所有的key
foreach(Object item in array.Keys)

{
	Console.WirteLine(item);
}
//遍历所有的Value
foreach(Object item in array.Values)

{
	Console.WirteLine(item);
}

3.泛型和泛型集合

泛型引入了一个概念:类型参数。通过使用类型参数(T),减少了运行时强制转换或装箱操作的风险,比较经典的泛型集合是List和Dictionary<K,V>。

3.1. List<>
List<T> 对象名=new List<T>();

""中的T可以对集合中的元素类型进行约束,T表明集合中管理的元素类型;

List的使用方法和ArrayList类似,只是List无须类型转换;

​ List与ArrayList的区别:

ListArrayList
不同点对所保存元素进行类型约束可以增加任何类型
添加/读取值类型元素无须拆箱和装箱添加/读取值类型元素需要拆箱和装箱
相同点通过索引访问集合中的元素
添加元素方法相同
删除元素方法相同
3.2.Dictionary<K,V>
Dictionary<K,V> 对象名=new Dictionary<K,V>();

说明:<K,V>中K表示集合中Key的类型,V表示Value的类型

例如:

Dictionary<string,SE> eng=new Dictionary<string,SE>();

eng集合的Key类型是string型,Value是SE类型;

​ Dictionary<K,V>和Hashtable的对比:

Dictionary<K,V>Hashtable
不同点对保存元素进行类型约束可以增加任何类型
添加/读取值类型元素无须拆箱和装箱添加/读取值类型元素需要拆箱和装箱
相同点通过Key获取Value
添加元素方法相同
删除元素方法相同
遍历方法相同

3.泛型类

使用泛型类,可以封装不是特定于具体数据类型的操作。定义泛型类的过程,与定义一个类相似,不同之处在于,尖括号里定义了类型参数;

public class 类名<T>
{
	//.....
}

T指类型参数,代表具体的数据类型,可以是类类型,也可以是基本数据类型。

泛型有以下优点:

  1. 性能高

  2. 类型安全

  3. 实现代码的重用

  4. 可以选择自己想用的数据类型

四.深入类的方法

1.构造函数

构造函数的用处

用于new对象。兼职:用于给成员变量赋值

构造函数具有以下特点:

  • 方法名和类名相同
  • 没有返回值类型
1.1无参构造函数

在默认的情况下,系统会给类分配一个隐式无参构造函数,并且没有方法体;

访问修饰符 类名()
{
	//方法体
}

也可以自定义无参构造函数(显式);

1.2带参构造函数(显式)

一般来讲,给方法设置参数可以调整方法的行为,使方法多样化。同样,构造函数也可以接收参数,用这些参数给属性赋值。语法如下:

访问修饰符  类名(参数列表)
{
	//方法体
}

在调用带参函数时需要注意的几点:

  • 参数的个数要对应
  • 参数的数据类型要一一对应;

2.方法重载(多态)

在面向对象的语言中,允许我们在同一个类中定义多个方法名相同,参数列表(参数个数,参数类型)不同的方法,称为方法重载;

方法重载的特点

  1. 在同一个类中;
  2. 方法名相同;
  3. 方法参数类型不同或者参数个数不同;
class PM
{  
    public void Show()
    {
        Console.WriteLine(" ");
    }
    
    public void Show(string name)
    {
        Console.WriteLine("名字是:{0}"+name)
    }
}

3,对象交互

在面向对象的世界里,一切皆为对象,对象与对象相互独立,但在一定外力的作用下,对象开始共同努力;

每个类都有自己的特性和功能,我们把它封装为属性和方法。对象之间通过属性和方法进行交互,可以认为方法的参数及方法的返回值都是对象间相互传递的信息。

六,初识继承和多态

1.继承的概述

1.1什么是继承

简单来说,继承就是子承父

生活中最简单的继承关系:

汽车(父类,基类

卡车和公共汽车(子类,派生类

1.2base关键字和protected修饰符
1.2.1base关键字

在子类中使用,可以调用父类的属性,还可以用base关键字调用父类的方法及父类的构造函数。

public class Employee
{
	public string Name{get; set;}
}
public class PM:Employee
{
	Console.WriteLine("名字是",base.Name)
}
1.2.2访问修饰符的限制:
修饰符类内部子类其他类
public可以可以可以
private可以不可以不可以
protected可以可以不可以

小结:子类可以调用父类的所有非private成员

1.3继承中构造函数

注意:每一个子类的构造函数一定会调用父类的构造函数

  • 没有明确指明,或使用:base()则调用父类的无参构造函数
  • 若使用:base(实参),则明确指明父类中的某个构造函数(根据参数个数以及类型)

2.继承的使用

2.1 继承的特性

注意:当类被sealed修饰时,该类为密封类,不允许被继承

2.1.1.继承的传递性:

正如人类有爸爸,也有爷爷

汽车有子类卡车,而卡车又可以有子类小型卡车,大型卡车

可以说汽车也是小型卡车,大型卡车的父类

此所谓继承的传递性

2.1.2继承的单根性:

假设某个人既有程序员的天赋,又有音乐家的气质,但是在C#中是不能明确规定的,一个子类不能提示继承多个类。

2.2 is a 的应用
if(emp is SE)
{
	Console.WriteLine(((SE)emp).Sahi());
}
if(emp is PM)
{
	Console.WriteLine(((PM)emp).Sahi());
}

在上列代码中使用 is 关键字,这个关键字用来判断对象是否属于给定的类型,如果属于则返回true,否则返回false;

2.3继承的价值

①继承模拟了现实世界的关系,OOP中强调一切皆为对象,这符合我们面向对象编程的思考方向。

②继承实现了代码的重用,合理的使用继承,会使代码更加简洁。

③继承使得程序结构清晰,子类和父类的层次结构清晰。

3.继承的优点
  1. 提高代码的重用性
  2. 形似父类,异于父类,保持个性
4.继承的缺点
  1. 继承编程侵入式
  2. 增加耦合

3.多态

3.1 虚方法

我们可以在父类和子类中定义如下的方法:

public virtual string Sayi()  //在父类中使用关键字virtual
{
	//省略方法体
}
public override string Sayi()  //在子类使用时是有关键字override
{
	//省略方法体
}

像这种virtual关键字修饰的方法,称为虚方法,虚方法有方法体,语法如下:

访问修饰符 virtual 返回值类型 方法名()//父类
{
	//方法体
}
访问修饰符 override 返回值类型 方法名()//子类
{
	//方法体
}

父类中定义的虚方法并非必须被子类重写,在父类中可以给出虚方法的默认实现。如果子类不重写父类的虚方法,依然执行父类的默认实现,如果子类重写了父类的虚方法,执行子类重写后的方法。

虚方法的特点

前提:两个类有继承关系

  1. 不同类
  2. 相同的方法名
  3. 相同的参数(个数,类型)
  4. 子类可以不重写父类方法

子类调用父类

根据方法名与参数调用,而不根据访问修饰符和返回值类型

七,深入理解多态

1.里氏替换和多态应用

1.1 里氏替换概述

子类对象可以赋给父类对象,也可以说子类可以替换父类,并且出现在父类能够出现的地方,且程序的行为不会发生变化,但是反过来,父类对象是不能够替换子类对象的,这种特性被称为:“里氏替换原则”;

“里氏替换原则”:是软件设计应该遵守的重要原则之一,有了里氏替换原则,才使继承复用成为可能。

小结引用父类的地方,都可以透明的使用子类对象

1.2 is 和 as操作符的使用

is操作符用于检查对象和指定的类型是否兼容,而as操作符用于对象之间的类型转换:

if(emp[i] is SE)
{
	PM pm=emp[i] as PM;
}

先用 is 关键字判断员工类,再用 as 关键字将此员工对象转换为对应的的类。

里氏替换原则提出子类对象可以替换父类对象,在编写时以父类类型作为形式参数的方法,在实际调用时传入子类对象。

2.抽象类和抽象方法

2.1为什么使用抽象类和抽象方法

抽象方法是一个没有实现的方法,通过在定义方法时增加关键字 abstract 可以声明抽象方法,其语法如下:

访问修饰符  abstract 返回类型 方法名();

注意:抽象方法没有闭合的大括号,而是直接跟一个分号 “:”也就是说,它没有包括方法执行逻辑的方法体。

1.含有抽象方法的类必然是抽象类,同样,我们用关键字 abstract 来定义一个抽象类,语法如下:

访问修饰符 abstract class 类名{}
2.2 抽象类和抽象方法的应用

1.如何实现抽象方法

从一个抽象父类派生一个子类时,子类将继承父类的所有特征,包括它未实现的抽象方法。抽象方法必须在子类中实现,除非它的子类也是抽象类,与子类重写父类的虚方法一样,在子类中也是使用 “override”关键字来重写抽象方法。

访问修饰符 override 返回类型 方法名();

举例一个示例:

public abstract class SE
{
	public abstract void Run(); //抽象方法不能有方法体
}

public void PM:SE
{
	public override void Run(){}  //继承SE的Run方法
}
2.3抽象方法的特点:
  1. 在不同的类中
  2. 有相同的方法名
  3. 相同的参数
  4. 没有方法体
  5. 抽象方法只能位于抽象类中
  6. 父类里面的抽象方法子类必须实现,用关键字 override(除非子类也是抽象类)
2.4抽象类特点
  1. 不能new对象
  2. 不能用sealed和static修饰
  3. 可以有抽象方法,也可以有普通方法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值