1.7 基本代码技巧

这里描述一些应用场景下,可以提高性能的基本代码技巧。对处于关键路径的代码,进行这类的优化还是很有意义的。普通代码可以不做要求,但养成一种好的习惯也是有意义的。

1.7.1 循环写法

可以把循环的判断条件用局部变量记录下来。局部变量往往被编译器优化为直接使用寄存器,相对于普通从堆或栈中分配的变量速度快。如果访问的是复杂计算属性的话,提升效果将更明显。

  1. for (int i = 0, j = collection.GetIndexOf(item); i < j; i++)
  • 需要说明的是:这种写法对于CLR集合类的Count属性没有意义,原因是编译器已经按这种方式做了特别的优化。

1.7.2 拼装字符串

拼装好之后再删除是很低效的写法。有些方法其循环长度在大部分情况下为1,这种写法的低效就更为明显了:

  1. public static string ToString(MetadataKey entityKey)
  2. {
  3. string str = "" ;
  4. object [] vals = entityKey.values;
  5. for ( int i = 0 ; i < vals.Length; i ++ )
  6. {
  7. str += " , " + vals[i].ToString();
  8. }
  9. return str == "" ? "" : str.Remove( 0 , 1 );
  10. }
  • 推荐下面的写法:
  1. if (str.Length == 0 )
  2. str = vals[i].ToString();
  3. else
  4. str += " , " + vals[i].ToString();

其实这种写法非常自然,而且效率很高,完全不需要用个Remove方法绕来绕去。

1.7.3 避免两次检索集合元素

获取集合元素时,有时需要检查元素是否存在。通常的做法是先调用ContainsKey(或Contains)方法,然后再获取集合元素。这种写法非常符合逻辑。

但如果考虑效率,可以先直接获取对象,然后判断对象是否为null来确定元素是否存在。对于Hashtable,这可以节省一次GetHashCode调用和n次Equals比较。

如下面的示例:

  1. public IData GetItemByID(Guid id)
  2. {
  3. IData data1 = null ;
  4. if ( this.idTable.ContainsKey(id.ToString())
  5. {
  6. data1 = this .idTable[id.ToString()] as IData;
  7. }
  8. return data1;
  9. }
  • 其实完全可用一行代码完成:return this.idTable[id] as IData;

1.7.4 避免两次类型转换

考虑如下示例,其中包含了两处类型转换:

  1. if (obj is SomeType)
  2. {
  3. SomeType st = (SomeType)obj;
  4. st.SomeTypeMethod();
  5. }
  • 效率更高的做法如下:
  1. SomeType st = obj as SomeType;
  2. if (st != null )
  3. {
  4. st.SomeTypeMethod();
  5. }