重温C# clr 笔记总结
作者:
1: .net framework 由两个部分组成:CLR 和 FCL。
2:在CLR中,所有错误都是通过异常来报告的。
3:智能感知功能主要是靠解析元数据实现的。
4:允许在不同语言之间方便的切换,并对各种语言进行紧密集成是CLR的出色特性。
5:一个方法只有在首次运行时才会由于jit造成一定的性能损失,以后对该方法的调用都以本地代码的形式全速运行。
6:方法签名指定了参数的数量(及其顺序),参数的类型;方法是否有返回值,如果有返回值,还要指定返回值的类型。
7:无论使用哪一种语言,类型的行为是完全一致的,因为类型的行为最终由CLR的CTS来定义。
8:使用[assembly:CLSCompliant(true)] 来检查CLS的相容性。
9:在同一程序集中,类型默认是internal,有一个原则是微软总是选择公开程度最低的关键字,比如默认的private。
10:在CLR中一个类型的每个成员要么是一个字段,要么是一个方法。
11:应答文件csc.rsp 的作用,使用/noconfig 开关忽略局部和全局csc.rsp.
12:元数据:二进制数据块,由几张表构成:分为3类:a:定义表,b:清单表,c:引用表。
13:一个托管的PE文件由4个部分构成,PE32(+)头,CLR头,元数据,IL。
14:程序集是一个或多个类型定义文件及资源文件的集合。
15:程序集允许我们分离可重用类型的逻辑和物理表示,如果一个程序集没有用到,那么它将永远不会下载。
16:为了生成一个新的程序集,来自一个引用程序集的所有文件都必须存在,但运行一个应用程序时,引用的程序集的所有文件不一定要全部存在。
17:程序集的版本号格式:主版本号,副版本号,Build号,Revision号。
18:[assembly:AssemblyCulture(“de-ch”)] 将程序集的语言文化设置为瑞士德语。
19:使用msi文件可以实现“即需安装”。
20:弱命名程序集之所有会成为问题,是因为几个不同的程序集可能具有相同的弱名称。
21:“Dll Hell” 根源:共享的Dll全部被复制到System32 目录中,弱命名的名称可能相同,最后安装的会覆盖前面的程序集。
22:之所以能将程序集拖放进GAC 依靠的是windows explorer shell (扩展) shFusion.dll.
23:在命令窗口cmd下,进入gac目录 查看gac的结构。
24:在安装.net framework 时,会安装两套副本,一套编译器/CLR目录,另一套:GAC 子目录。
25:ToString 方法默认反悔this.GetType().FullName.
26:GetType方法是非虚方法,这样就可以防止一个类重写该方法,隐瞒其类型,破坏安全性。
27:命名空间和程序集没什么关系。
28:堆上的所有对象都包含两个额外的成员:类型对象指针和同步块索引。
29:System.Object 的GetType方法返回的是存储在指定对象的“类型对象指针”成员中的地址。
30:GetType方法返回的是指向对象的类型对象的一个指针。
31:编译器直接支持的任何数据类型称为基元类型。
32:在代表值类型实例的一个变量中,并不包含一个指向实例的指针,相反变量中包含实例本身的字段。
33:文档将所有值类型都称为一个结构 或一个枚举。
34:假如知道自己写的代码会造成编译器反复对一个值类型进行装箱,那么换用手动方式对值类型进行装箱,代码会更小更快。
35:总结第34条:降低调用浪费资源耗费时间多的步骤的次数。
36:使用接口的方式可以允许我们更改一个已装箱对象的字段,在C#中,不使用接口的方法是达到这个目的的。因为这个方式有点绕,所以不推荐使用需要修改字段的值类型,在设计模式中,值类型是不变的类型。
37:在内部,ValueType的Equals 方法使用反射技术来完成字段的比较,因为反射比较慢,所以在定义自己的值类型时,应重写Equals方法,不要调用base.Equals.具体的重写步骤如下:
a:如果obj == null –> false;
b: 参数引用不同对象 -> false;
c:每个字段都相等 –>check ->不相等(false)
d:true.
因为正确的重写Equals 方法比较复杂,在性能要求不是很严重的地方,可以不重写。
38:在需要修改一个哈希表的健值对时,正确的做法是 先移除再添加。
39:不要对哈希码 进行持久化 ,因为哈希码很容易改变,例如一个未来的版本可能使用一个不同的算法来计算对象的哈希码。
40:元数据的格式与源代码所使用的编程语言无关,因此元数据的格式都是相同的,元数据是所有语言都可以生成和使用的公共信息,是.net framework 开发平台的关键,它允许编程语言,类型和对象之间无缝集成。
41:对于任何可访问的成员,都必须定义在一个可见的类型内。
PS:类如果都看不到,你还能看到类里面的东西吗?
42:类型的可见性:public internal(默认)
成员的可见性:public protected private (默认)
43:CLR要求接口的所有成员都是公开的, 接口是个契约,是个合同,所以成员都公开才有意义。
44:C# 编译器要求原始成员和重写成员必须具有相同的可访问性,CLR 允许成员的可访问性约束更低,而不允许更高。如果父类的某个方法是protected,那么子类重写这个方法的时候,可以选择约束更低的
public ,但是不能选择约束更强的private。
44:关键字 static 仅仅可以应用于类,不能应用于值类型(结构,枚举),因为值类型必须实例化,并且没有办法停止和阻止该过程。
45:静态类必须直接继承 System.Object ,因为继承性仅仅适用于对象。
46:静态类不能实现任何接口,因为只有使用类的实例才能调用接口的方法,可是静态类不能实例化。
47:只能定义静态成员,因为静态类不能实例化。
48:编译器不会在静态类 类型中生成实例构造器方法。
49:C# 编译器 完全支持部分类(partial type) 特征,但是CLR 却完全不支持,甚至CLR根本就没有
partial关键字。
50:对于类型字段:CLR 会在首次引用类型时才创建动态内存,也即jit 编译。
对于实例字段,创建类型实例时才分配存放字段的动态内存。
51:如果一个字段属于引用类型,并且被标记为readonly ,不可改变的是这个引用本身,而不是它所引用的对象。
52:构造器是允许将类型实例初始化为有效状态的特殊方法。
53:如果有多个实例构造器,最好通过this关键字先调用默认无参构造函数,然后再赋值。
public SomeType(int x,int y):this(){}
54:所有值类型的构造器必须初始化值类型的所有字段,因为值类型的任何字段必须在读取之前进行初始化。
55:类型构造器 最多只有一个,并且永远没有参数。
56:因为CLR保证每个应用程序域的类型构造器只执行一次,而且是线程安全的,所以最适合构造
singleton 模式
57:如果希望应用程序域关闭时能执行某些代码,我们可以在System.AppDomain的DomainUnload事件中注册一个回调方法。
58:当编译器查找FCL 中的核心数值(Int32,Int64)等基元类型的操作符时,会生成直接操作的IL指令,所以核心FCL 类型不能定义任何操作符重载方法的原因,因为方法调用会影响效率。
59:CLR规范将转换操作符重载方法定义为public 和static 方法。
60:只有方法的最后一个参数才可以使用params 关键字。
61:属性不能作为out 或ref 参数传递给方法,字段则可以。因为属性的本质是getter 和 setter.
62:C# 编译器 只允许接口定义方法,因为 事件,属性,索引器 本质上都是方法,所以也允许在接口中定义他们。