随笔分类 -  CLR via C#

类型构造器的性能
摘要:调用类型构造器并不那么简单,JIT编译器不得不决定是否生成调用它的代码,并且CLR要确保调用是线程安全的。当编译器决定发起一个调用来执行类型构造器,它必须判断是否应该这样做,有两种可能性:1.JIT在创建类型的第一个实例的代码之前立即发起或者在访问类的非继承的字段,成员的代码之前立即调用2.JIT在首次访问一个静态字段,静态方法,实例方法,或调用一个实例构造器的代码之前某个时间调用,因为CLR要确保静态构造器在其他成员被访问之前运行。 先来看一下代码: internal sealed class BeforeFieldInit { public static I... 阅读全文
posted @ 2013-08-27 11:35 二豆 阅读(394) 评论(0) 推荐(0) 编辑
常量和字段
摘要:常量是一个特殊的符号,它有一个从不变化的值。定义常量符号时,它的值必须能在编译时确定。确定之后,编译器将常量的值保存到程序集的元数据中。这意味着只能为编译器认定的基元类型定义常量。在C#中一下类型都是基元类型,可用于定义常量:boolean,char,byte,sbyte,int16,int32,int64,Uint16,Uint32,Uint64,single,double,decimal和string。然后C#也允许定义一个非基元类型的常量变量,前提是把它的值设为null。 定义常量将导致创建元数据。代码引用一个常量符号时,编译器会在定义常量的程序集的元数据中查找改符号,提取常量的值... 阅读全文
posted @ 2013-08-25 20:33 二豆 阅读(509) 评论(0) 推荐(1) 编辑
装箱与拆箱
摘要:在上一篇中提到:装箱需要在托管堆上分配额外的对象,将来必须对其进行垃圾回收,所以不必要的,额外的装箱应尽量避免,否则会影响程序的性能和内存消耗,那么装箱是怎样影响程序性能的呢? 先来看一段示例代码: struct Point { public Int32 x, y; } class Program { static void Main() { ArrayList a = new ArrayList(); Point p; for (Int32 i = ... 阅读全文
posted @ 2013-08-21 20:27 二豆 阅读(292) 评论(0) 推荐(1) 编辑
那些年我们说过的值类型与引用类型
摘要:CLR支持两种类型:引用类型和值类型,虽然FCL中大多的类型都是引用类型,但是我们程序员用得最多的还是值类型。引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址---也就是指向对象数据的内存地址,引用类型有以下特点:内存必须从托管堆上分配。堆上分配的对象都有一些额外的成员,这些成员必须初始化。从托管堆上分配一个对象时,可能强制执行一次垃圾收集操作。 托管堆的概念,简单的说,所有的.NET语言在分配引用类型对象时都要使用托管堆。像值类型这样的轻量级对象始终分配在栈中,但是所有的类实例和数组都被生成在一个内存池中,这个内存池就是托管堆。托管堆的更深入理解请看这里:http:... 阅读全文
posted @ 2013-08-18 21:22 二豆 阅读(1000) 评论(4) 推荐(2) 编辑
关于静态方法与非静态方法的执行效率
摘要:以前看到许多网友认为静态方法要比实例方法在执行效率上要快一些,当初不敢苟同。自己亲自试了一把,发现静态方法确实要快一些。 想要比较静态方法与非静态方法的执行效率,需要对CLR在调用静态方法与非静态方法时的不同之处要有一个了解。 静态方法是与类相关联的,CLR在调用一个静态方法时需要做的事情就是找到定义该方法的类型即可实现调用;而在调用非静态方法时,为了保证运行安全,CLR会对我们的源代码进行验证并额外的生成一些IL中间代码来确保运行安全,所以在调用一个非静态方法时,CLR首先是判定被调用对象是否为NULL,如果为NULL,则引发一个异常,反之,则根据对象推荐出其类型,最后实现调用。可以... 阅读全文
posted @ 2013-08-15 10:27 二豆 阅读(6558) 评论(10) 推荐(4) 编辑