【原创】《.NET本质论》读书笔记(一)

类型基础

CLR的Type是可重用抽象体,就是把module再细分的结果。Type的描述存放在CLR的module的元数据中,module里同时存着使type工作的CIL(common intermediate language)或本机代码(machine code).

 

Type的强命名包括三部分:assembly name, namespace prefix, type name.

 

以下记录几个容易混淆的东西。

1、access control

     public是所有类可见

     internal是指在type所属程序集可见

     protected是指type自身和子类可见

     private是指自身可见

其中,internal和protected是可组合使用的。另外有一个sealed关键字,是用来指示此类(或方法)不可被继承(或覆写即override)。

问题:对于父类private的字段,子类中含有这个字段吗?当然有,只是子类不能访问罢了。继承时,类的内存分配是按照field的大小来分配的,子类中当然也有父类private字段,只是不能访问。

 

2、可变参数列表 variable parameter list

    CLR的System.ParamArrayAttribute属性应用到最后一个参数上,指定可变参数列表,当然,类型只能是参数数组定义的类型了。例如:

可变参数列表

 

 

3、嵌套类型 Nested Type

     java中的嵌套类型是跟随所属类进行实例化的,CLR中的嵌套类型是static成员,是不能被逐一实例化的。例如:

Nested Types in C#

 

4、字段的static、const、readonly关键字

static是说这个字段是type级别而不是object级别的,所以在内存中这个type的所有实例共享这个字段。这个字段是在type被CLR首次加载的时候分配内存的,初始化也在这个时候。

const和readonly字段都是说这个值不能改变、只能赋值一次,不同之处在于:const是编译时就赋值的,readonly则是在运行时赋值。所以const是字面值,而readonly是根据运行时提供值决定的。

 

5、类型初始化函数 .cctor

每个类都有自己的构造函数,这个构造函数体在代码中由new来调用;而每个type都有自己的类型构造函数,这个是CLR加载type时候调用的,我们的代码不能调用。

那什么时候CLR调用这个.cctor呢?本来在加载一个type时就该调用了,但是有一个元数据属性beforefieldinit,如果有这个属性的话,调用.cctor就推迟到第一个static field被引用时才调用。这个beforefieldinit是元数据字段,所以是编译器自己加上的。在.net framework中,当你的type没有.cctor只有ctor时,中间语言编译器就自动在IL中加入beforefieldinit标记了。如下图:

没主动写.cctor时


上面这段代码编译后的IL如下

image

Program类有一个.cctor,而且其IL代码如下,只要没有显式定义.cctor, beforefieldinit属性就会出现。

.class private auto ansi beforefieldinit LinaTest.Program extends [mscorlib]System.Object { } // end of class LinaTest.Program

注意:如果Program类中没有上述代码中的static int i=0 的话,IL中就不会有.cctor了,但是beforefieldinit属性还是有的。说明, 有静态字段初始化表达式才会有隐式.cctor出现(这个是什么原因我还不知道,难道可以没有.cctor吗?)

 

posted @ 2010-03-14 19:48  linaelf  阅读(391)  评论(0编辑  收藏  举报