1、显式注册的EvenHandler要显式注销以避免内存泄漏
将一个成员方法注册到某个对象的事件会造成后者持有前者的引用。在事件注销之前,前者不会被垃圾回收。
由事件引起的内存泄漏问题:
对象A订阅了对象B中的事件
对象A的生命周期远远大于对象B
对象A没有取消订阅对象B的时间
最终导致对象B无法释放
2、控件绑定的数据源批量操作应避免自动刷新
客户端批量操作数据时,控件自带的刷新操作,会造成不必要的时间消耗
当数据源(如DataTable、Array、List、ObservableCollection或其他IListSource等)被绑定到控件时,批量操作数据时应该断开绑定或挂起控件的刷新。this.gcBillList.DataSource = null; DataRowCollection rows = this.ds.Tables[0].Rows; foreach (DataRow row in rows) { // DataRow数据操作 } this.gcBillList.DataSource = this.ds.Tables[0].DefaultView;
3、减少客户端与服务端的通信次数
WebService调用并非越少越好,传输数据量较大的情况可考虑拆分为多次调用
对于短WebService的调用,应尽量合并以减少交互次数//多次调用了相同的WS txtCompanyName.Text=SCPubFunctionClient.PublicWSCal<string>(“ForTest”, “GetCompanyNameByID”,“0001”); txtCompanyInnerName.Text=SCPubFunctionClient.PublicWSCal<string>(“ForTest”, “GetCompanyInnerNameByID”,“0001”); //合并相邻的WS string[] result=SCPubFunctionClient.PublicWSCal<string>(“ForTest”, “GetCompanyNameAndInnerNameByID”,“0001”); txtCompanyName.Text=result[0]; txtCompanyInnerName.Text= result[1];
4、减少客户端与服务端的通信次数
如非必要,应尽量避免在循环体内重复调用WebService
装箱操作会造成GC压力;如果发生在集合中,应该使用泛型集合避免。
对于值类型的集合,使用List<T>来代替ArrayList,使用Dictionary<TKey, TValue> 来代替Hashtable。ArrayList h=new ArrayList(); //不建议 h.Add(1); List<object> h = new List<object>(); //不建议 h.Add(1); List<int> h = new List<int>(); //建议 h.Add(1);
6、字符串操作: C# 字符串操作--减少垃圾回收压力
7、使用常量避免创建对象
如下例,程序中存在大量 new decimal(0)的代码,,这会导致小对象频繁创建及回收;正确的做法是使用 Decimal.Zero 常量。private string CurrencyCalc() { if (firstValue == new decimal(0)) …… if (secondValue == new decimal(0)) …… if (thirdValue == new decimal(0)) …… if (fourthValue == new decimal(0)) …… …… }
8、避免不必要的抛出异常
C# 异常处理(Catch Throw)IL分析
9、使用RemoveAll而非RemoveAt进行删除多个元素
使用RemoveAll方法对集合(如List)中的多个元素进行一次性删除时,只会对List的内部数组做一次resize 操作,效率明显高于循环调用RemoveAt。List<string> lst = new List<string> {"1", "2", "3", "1", "2", "4"}; //不建议: for (int i = lst.Count - 1; i >= 0; i--) { if (lst[i] == "1" || lst[i] == "2") { lst.RemoveAt(i); } } //建议: lst.RemoveAll(s => s == "1" || s == "2");
10、C# DataSet性能最佳实践
11、反射与动态绑定--减少CPU占用
反射技术是将编译期间的静态绑定转换为延迟到运行期间的动态绑定。
C#主要支持 5 种动态创建对象的方式(时间消耗来自网络,与我实测的差距挺大,具体测试见下方):
动态创建对象的方式与Direct Create
1.Type.InvokeMember
慢40倍以上
2.ContructorInfo.Invoke
慢40倍以上
3.Activator.CreateInstance(Type)
慢7倍
4.Activator.CreateInstance(assemblyName, typeName)
慢1000倍以上
5.Assembly.CreateInstance(typeName)
慢40倍以上