全局程序集缓存(GAC),放进GAC的程序集称为共享程序集
- 只有强命名程序集能被添加到GAC
- GAC不仅值接受.dll扩展名的文件,也可以添加带.exe扩展名的程序集
- GAC位置在名称为Assembly的子目录下,在Windows系统目录中。
当试图安装一个程序集到GAC时,CLR的安全组件首先必须检验程序集上的数字签名是否有效。如果无效,系统不会把它安装到GAC。
GAC内的并肩执行
相同文件名的不同程序集(因为他们带有不同的标识符)
配置文件
配置文件含有关于应用程序的信息,供CLR在运行时使用。
配置文件有XML代码组成,并不包含C#代码。
他们的一种用途是更新一个应用程序集以使用新版本的DLL
异常
异常是程序中的运行时错误,他违反了一个系统约束或应用程序约束,或出现了在正常操作室未预料的情形。
try语句用来知名被异常保护的代码块,并提供代码以处理异常。
- try块包含正被异常保护的代码
- catch子句部分含有一个或多个catch子句。这些是处理异常的代码块。它们也称为异常处理程序。
-
finally块含有在所有情况下都要执行的代码,无论有没有异常发生。
当一个异常发生时,CLR:
- 创建该类型的异常对象。
-
寻找适当的catch子句已处理它。
所有异常类都从根本上派生自system.exception类。异常继承层次的一个部分如图
异常对象含有只读属性,带有导致该异常的信息。
catch子句处理异常,它有三种形式,允许不同级别的处理。
为异常寻找处理代码
一般法则
结构
结构有数据成员和函数成员。关键字struct。
结构与类最重要的区别:
- 类是引用类型而结构是值类型
- 结构是隐式密封的,而这意味着他们不能被派生。
-
声明结构的语法与声明类相似
结构是值类型和所有值类型一样,结构类型变量含有它自己的数据。从而:
- 结构类型的变量不能为null;
- 两个结构变量不能引用同一对象;
类变量赋值和结构变量赋值
结构可以有实例构造函数和静态构造函数,但不允许有析构函数。
构造函数和析构函数的总结
在结构中字段初始化是不允许的
结构是密封的(隐式密封),不能从他们派生其他结构。
不能用于结构的修饰符
- protected
- internal
- abstract
- virtual
结构作为返回类型和参数。
结构可以作为返回值和参数
- 返回值:当结构被作为返回值时,一个拷贝被创建并从函数成员返回
- 值参:当结构被用作值参时,一个实际参数的拷贝被创建。该拷贝被用在方法的执行中。
- ref和out参数:如果把一个结构用作ref或out参数,一个对该结构的引用被传入方法,这样其他数据成员就能被改变
结构就像类可以实现接口
枚举
枚举是由程序员定义的类型,与类或结构一样。
- 值类型,直接储存它们的数据
-
只有一种类型的成员:命名的整数值常量。
注意成员声明列表是逗号分隔的,在枚举声明中没有分号
每个枚举类型都有一个底层证书类型,默认为int
数组
Rank:返回数组维度数的属性
Length:返回数组长度的属性
数组是引用类型,数组的元素可以是值类型或引用类型
一维数组
实例化数组
访问数组
使用索引值访问
显示初始化一维数组
int[] intArr = new int[] {1,2,3,4}
隐式类型数组
交错数组
成 员 | 类 型 | 生 存 期 | 意 义 |
---|---|---|---|
Rank | 属性 | 实例 | 获取数组的维度数 |
Length | 属性 | 实例 | 获取数组中所有维度的元素总和 |
GetLength | 方法 | 实例 | 返回数组的指定维度的长度 |
Clear | 方法 | 静态 | 设置元素的范围为0或null |
Sort 方法 | 方法 | 静态 | 在一维数组中对元素进行排序 |
BinarySearch | 方法 | 静态 | 使用二进制搜索,搜索一维数组中的值 |
Clone | 方法 | 实例 | 进行数组的浅复制——复制值类型数组和引用类型数组的元素 |
IndexOf | 方法 | 静态 | 返回一维数组中遇到的第一个值 |
Reverse 方法 | 方法 | 静态 | 将一维数组中的某一范围内的元素顺序倒过来 |
GerUpperBound | 方法 | 实例 | 获取指定维度的上限 |
clone方法
- 克隆值类型数组会产生两个独立的数组
- 克隆引用类型数组会产生两个指向相同对象的数组
委托
委托包含具有相同签名和返回类型的有序方法列表
- 方法的列表称为调用列表
- 当委托被调用时,他调用列表中的每一个方法
委托与C++的函数指正不同的是委托是面向对象的并且是类型安全的
调用列表中的方法
由委托保存的方法可以来自任何类或结构,只要他们同时匹配委托的如下两点: - 返回值
-
签名
调用列表中的方法可以使实例方法或是静态方法
委托类型声明和所有类型声明一样,不需要在类内部声明
委托类型声明:
- 以delegate关键字开头
- 没有方法主体
委托是引用类型,因此有引用和对象
委托类型的变量的声明:
两种创建委托对象的方式:
由于委托是引用类型,可以通过给他赋值来改变包含在委托变量中的引用,就得委托对象会被垃圾回收期回收
组合委托
例:第三个委托有前两个委托组合
为委托增加方法
可以通过使用+=运算符来为委托增加方法或另一个委托
反之-=从委托移除方法
调用方法
调用带返回值的委托
如果委托有返回值并且在调用列表中有一个以上的方法,会发生下面的情况:
- 调用列表中最后一个方法返回的值就是委托调用返回的值。
- 调用列表中所有其他方法的返回值都会被忽略。
namespace weituo
{
delegate int MyDel();
public class MyClass
{
int result = 5;
public int Add2()
{
result += 2;
return result;
}
public int Add3()
{
result += 3;
return result;
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
MyDel md = mc.Add2;
md += mc.Add3;
md += mc.Add2;
Console.WriteLine(md());
Console.ReadKey();
}
}
}
返回结果:
12
匿名方法
匿名方法允许我们避免使用独立的具体方法。
匿名方法是在初始化委托时内联声明的方法
上图两组代码的输出结果为:
25
26
可以在如下地方使用匿名方法:
- 声明委托变量时作为初始化表达式;
- 组合委托时在赋值语句的右边;
- 为委托增加事件时在赋值语句的右边。
匿名方法表达式的语法包含如下组成部分:
- delegate类型关键字;;
- 参数列表,如果语句块没有使用任何参数则可以省略。
-
语句块,它包含了匿名方法的代码
返回类型需与委托的返回类型相同。
参数
除了数组参数,匿名方法的参数列表必须在如下三方面匹配委托: - 参数类型
- 参数数量
- 修饰符
当下列两个条件都满足的时候,可以省略匿名方法的参数列表: - 委托的参数列表不包含任何out参数
- 匿名方法不使用任何参数
params参数
如果委托声明的参数列表包含了params参数,那么params关键字就会被匿名方法的参数列表忽略。
变量和参数的作用域
参数以及声明在匿名方法内部的局部变量的作用域限制在实现方法的主体之内
匿名方法可以访问它们在外围作用域的局部变量和环境
外围作用域的变量叫做外部变量
用在匿名方法实现代码中的外部变量称为被方法捕获
Lambda表达式
匿名方法转换成Lambda
事件
事件就好像被简化的针对特殊用途的委托
事件是成员
- 由于事件不是类型,我们不能使用对象创建表达式(new表达式)来创建它的对象
- 由于事件是成员
- 他必须声明在类或结构中,和其他成员一样;
- 不能在一段可执行代码中声明事件
- 事件成员被隐式自动初始化null
触发事件
- 在触发事件之前和null进行比较,查看是否包含事件处理程序,如果事件为null,则表示没有’
- 触发事件本身看起来像调用函数一样
- 使用事件名称,后面跟的参数列表包含在圆括号中。
- 参数列表必须匹配事件的委托类型。
订阅事件
要为事件添加事件处理程序,处理程序必须有和事件委托一致的返回类型和签名
下列代码为事件增加了三个方法:第一个使用方法形式的实例方法,第二个是使用方法形式的静态方法,第三个是使用委托形式的实例方法。
使用匿名方法和lambda表达式增加事件处理程序
eventhandler委托类型
通过扩展eventargs来传递数据
事件访问器
- 有两个访问器;add和remove。
-
声明事件的访问器看上去和声明一个属性差不多
接口
接口是表示一组函数成员而不实现成员的引用类型。
其他类型——类和结构可以实现接口。