C#性能优化:类型系统

1.4.1 避免无意义的变量初始化动作

CLR保证所有对象在访问前已初始化,其做法是将分配的内存清零。因此,不需要将变量重新初始化为0、false或null。

需要注意的是:方法中的局部变量不是从堆而是从栈上分配,所以C#不会做清零工作。如果使用了未赋值的局部变量,编译期间即会报警。不要因为有这个印象而对所有类的成员变量也做赋值动作,两者的机理完全不同!.

1.4.2 ValueType 和 ReferenceType

1.4.2.1 以引用方式传递值类型参数

值类型从调用栈分配,引用类型从托管堆分配。当值类型用作方法参数时,默认会进行参数值复制,这抵消了值类型分配效率上的优势。作为一项基本技巧,以引用方式传递值类型参数可以提高性能。

1.4.2.2 为 ValueType 提供 Equals 方法

.net 默认实现的 ValueType.Equals 方法使用了反射技术,依靠反射来获得所有成员变量值做比较,这个效率极低。如果我们编写的值对象其 Equals 方法要被用到(例如将值对象放到 HashTable 中),那么就应该重载 Equals 方法。

public struct Rectangle{ public double Length; public double Breadth; public override bool Equals ( object ob) { if (ob is Rectangle)  return Equels ((Rectangle)ob))  else  return false ;  }  private bool Equals (Rectangle rect)  {  return this .Length == rect.Length && this .Breadth == rect.Breach; 
 } }

1.4.2.3 避免装箱和拆箱

C#可以在值类型和引用类型之间自动转换,方法是装箱和拆箱。装箱需要从堆上分配对象并拷贝值,有一定性能消耗。如果这一过程发生在循环中或是作为底层方法被频繁调用,则应该警惕累计的效应。

一种经常的情形出现在使用集合类型时。例如:

 ArrayList al = new ArrayList();  for ( int i = 0 ; i < 1000 ; i ++ )  {  al.Add(i); // Implicitly boxed because Add() takes an object  } 

int f = ( int )al[ 0 ]; // The element is unboxed