常数定义和字段定义的区别

本质的不同是,在运行时,对于常数不需要任何内存分配,但对字段,运行时会在字段所在的实例被创建时分配动态内存。

对于这点区别,有几个问题需要作相关的深入发现,

第一、正是因为常数没有相关的内存地址,编译器会在编译时就确定所有对常数符号的数值替换。Asp.net基于这个机制会产生版本问题,例如:

如果程序集B中的常数由于业务因素发生了变化,那么程序集B肯定是要重新编译的,但如果之前引用程序集B常数的其它程序集就不得不因此也要重新编译了。

否则常数值会一直会用之前的那个值。这就是所说的版本问题。

第二、 字段何时会被会被分配内存,

对于实例字段的情况,中间语言指令中有一个叫newobj被JIT编译生成机器指令时,会导致CLR计算所有字段所需空间,并

在Managed Heap中分配相应的空间。很多语言都有存象new这样的操作符,如c#,都会编译生成newobj这样的IL指令。 

还有一种情况,反序列化对象及MemberwiseClone作对象拷贝时,会分配内存,并初始化对象的成员,这部分代码因为是直接调用内核的C++代码来作。可能只是作字节的拷贝。 

对于类型字段的情况, 也就是静态字段,我个人认为是在类型被访问之前,会对类型作初始化,也就是调用类型的构造器,这时就会分配内存,可能会在之前。

引言:

注:因为有些方法在asp.net中,如system.objet.memberwiseclone()是标注[MethodImplAttribute(MethodImplOptions.InternalCall)] ,这部分代码用IL工具是看不到。

Internal calls end up making a call to a C++ function in the CLR. You can find them back in the Rotor source code. Look at clr\src\vm\ecall.cpp to find the mapping from the .NET visible name to the CLR function name. Beware that the source is getting dated. 

 (个人观点,欢迎指正,谢谢。) 

原文地址:https://www.cnblogs.com/malaikuangren/p/2447164.html