<<Clr Via C#>> Key Points (1) (4-6章)

.net框架那本书已读过几遍,但仍有一下地方的知识被遗漏.
重读此书,主要摘录了<<Clr Via C#>>中有些自己不知,或容易忽略的技术要点

前1-3章未读先跳过了

第4章

1) 认为GetHashCode不应该定义在Object类中,因为大多类不会在Hash Table中当key使用.应该设计成一个Interface,当需要做key时,去实现这样的interface就好了

2) CLR创建对象时都需要使用New操作符. (应该不全是,在后面的章节中有提到)

3) New操作符做了哪些事:

    1. 计算对象实例需要的内存空间.类自身定义的fields以及基类定义的fields,附带两个额外的成员: a.指向类型的指针 b. 用于同步的index(sync block index, 用于管理对象)
    2. 分配内存,将所有字节付0
    3. 初始化两个额外的成员
    4. 调用实例构造函数.
    5. 返回一个地址指针给变量

4) 实例构造函数会依次先调用基类的无参构造函数,每个构造函数负责初始化自身定义的Fields

5) CLR是类型安全的,所以在运行时总是知道对象的确切类型

6) CLR根本就不知道namespaces的存在,因此当它需要访问一个类型时,它需要知道此类型的完整名字.这点可以通过ildasm.exe工具查看生成的IL代码.所谓的别名也只是告诉编译器如何得到类型的完整名.

7) 一个thread被创建,会为其在stack上分配1MB空间.此空间用于传递参数,创建局部变量等.

8)

第5章

9) 应该为值类型重写Equals方法.因为ValueType是通过reflector实现Equals方法的,严重影响性能

10) C#编译器不允许值类型实现Finalize方法

11) System.Runtime.InteropServices.StructLayoutAttribute可以为类声明字段的布局方式

12) 如何在AppDomain里生成唯一的ID: 通过System.Runtime.CompilerServices.RuntimeHelpers类的GetHashCode()方法

13) ValueType实现GetHashCode使用reflection以及XOR一些字段.(实际上不完全是这样.应该是返回第一个不为null的field的hash code)

第6章

14) Friend Assemblies : 一般来说类型定义为internal访问权限的话,此成员只能被同一assembly其它类型访问.但由于某些特殊原因, 特定的另一个assembly成员想要访问次internal成员类型,那么就可以使用此技术

Using System.Runtime.CompilerServices

[assembly : InternalsVisibleTo(“assembly name, assembly key”)]

15) 子类型想要覆盖父类型的成员时, 在C#里他们的访问权限定义的必须一致.在CLR里,子类型还可以降低访问权限.

16) Static Class : 一直没注意原来C#也有静态类型.

静态类型约束:

      Ø 此类型必须直接继承自Object.因为此类型没有实例,所以继承自其它类型没有任何意义.

      Ø 不能实现任何interface

      Ø 只能定义静态成员

      Ø 此类型不能被用于私有成员,方法参数,局部变量.

17) 一般来说对于非虚方法使用call指令,对于虚方法使用callvirt指令.callvisrt指令会去检测当前对象是不是null,而且还需要查表,因此会慢一点.

object o = new object();

Type t = o.GetType();

查看IL却发现实际上是使用callvirt指令的,为何呢?这是C#编译器为了保证o对象不为空,因为callvirt指令会去检测o对象是否为null,而call指令不会.当JIT发现callvirt指令调用方法时,发现此方法不是虚方法,就会调用它的非虚方法,不需要再去查表.

18) 有时候编译器也会用call指令代替callvirt指令去调用虚方法.例如调用对象的ToString()方法.如何用callvirt指令去调用,会出现死循环(??why)

19) 优先使用非虚方法:

      Ø 调用虚方法要慢

      Ø 虚方法不能被inline

      Ø 虚方法使得版本控制更复杂

20) Jeff认为除了sealed之外应该增加closed来修饰class,子类不可以修改父类的任何行为,但可以扩充.

21) 当事情变得越来越负责的时候,添加更多的类

22) 标记一下: 字段前面还可以加volatile修饰, 表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。

posted @ 2007-06-11 10:22  Anders06  阅读(495)  评论(0编辑  收藏  举报