1.7 基本代码技巧
这里描述一些应用场景下,可以提高性能的基本代码技巧。对处于关键路径的代码,进行这类的优化还是很有意义的。普通代码可以不做要求,但养成一种好的习惯也是有意义的。
1.7.1 循环写法
可以把循环的判断条件用局部变量记录下来。局部变量往往被编译器优化为直接使用寄存器
,相对于普通从堆或栈中分配的变量速度快。如果访问的是复杂计算属性的话,提升效果将更明显。
for (int i = 0, j = collection.GetIndexOf(item); i < j; i++)
- 需要说明的是:这种写法对于CLR集合类的Count属性没有意义,原因是编译器已经按这种方式做了特别的优化。
1.7.2 拼装字符串
拼装好之后再删除是很低效的写法。有些方法其循环长度在大部分情况下为1,这种写法的低效就更为明显了:
public static string ToString(MetadataKey entityKey)
{
string str = "" ;
object [] vals = entityKey.values;
for ( int i = 0 ; i < vals.Length; i ++ )
{
str += " , " + vals[i].ToString();
}
return str == "" ? "" : str.Remove( 0 , 1 );
}
- 推荐下面的写法:
if (str.Length == 0 )
str = vals[i].ToString();
else
str += " , " + vals[i].ToString();
其实这种写法非常自然,而且效率很高,完全不需要用个Remove方法绕来绕去。
1.7.3 避免两次检索集合元素
获取集合元素时,有时需要检查元素是否存在。通常的做法是先调用ContainsKey(或Contains)方法,然后再获取集合元素。这种写法非常符合逻辑。
但如果考虑效率,可以先直接获取对象,然后判断对象是否为null来确定元素是否存在。对于Hashtable,这可以节省一次GetHashCode调用和n次Equals比较。
如下面的示例:
public IData GetItemByID(Guid id)
{
IData data1 = null ;
if ( this.idTable.ContainsKey(id.ToString())
{
data1 = this .idTable[id.ToString()] as IData;
}
return data1;
}
- 其实完全可用一行代码完成:
return this.idTable[id] as IData;
1.7.4 避免两次类型转换
考虑如下示例,其中包含了两处类型转换:
if (obj is SomeType)
{
SomeType st = (SomeType)obj;
st.SomeTypeMethod();
}
- 效率更高的做法如下:
SomeType st = obj as SomeType;
if (st != null )
{
st.SomeTypeMethod();
}