1、異常的構成數據庫
new Exception() 建立異常對象性能
throw 拋出異常對象(主要性能損耗位置)測試
try{}catch{} 捕捉異常對象this
C#裏面異常對象分爲兩個子類ApplicationException、SystemException,前者主要是提供給應用程序自定義的異常類,後者是提供給系統定義的異常類spa
2、如何使用異常pwa
異常的正常邏輯是:由底層拋出,由高層處理code
一、底層方法或者提供給其餘人使用方法內的一些參數過濾或其它異常應該向上拋出對象
如(借鑑現成代碼懶得寫了):blog
public void InsertUser(User user) { if(user==null) { throw new ArgumentNullException("參數user爲null"); } //調用Orm }
二、上層應該加上try{}catch{}來捕捉異常並處理繼承
如:
try { bll.InsertUser(null); } catch (ArgumentNullException e) { LogHelper.Write(e.Message); }
三、避免一些錯誤的異常處理方式
如(借鑑現成代碼懶得寫了):
/* 用異常驗證用戶輸入 用戶輸入的合法性驗證是屬於業務邏輯的一部分,絕對不要用異常去處理,注意,是用戶輸入,因此這個經驗僅限於表現層邏輯 */ //典型錯誤1 try { int i=int.Parse(textBox1.Text); } catch(Exception ex) { alert(「不要輸入非數字」); } //典型錯誤2 void ValidateInput(int i) { if(i<0&&i>100) { throw new Exception("輸入數據範圍錯誤"); } } /* 將異常交由給底層處理 這個錯誤在於徹底不驗證用戶輸入而直接把數據的驗證拋向數據庫,等待數據庫報錯來判斷用戶輸入的正確性,這個是很是致命的錯誤,不少注入漏洞都是由此產生的 */ //典型錯誤3 try { string name=Request.QueryString["xx"]; List<User> userls=User.QueryUserByName(name); } catch(SqlException ex) { } /* 徹底不用異常機制 產生這個錯誤確定是一個很是腦殘的決定形成的。不過不少時候某些不瞭解異常機制的人,因爲對異常的性能開銷的恐懼感,常常會作出這麼腦殘的決定 性能卻是高了,可是系統異常怎麼辦呢?一旦數據庫出錯就只等着系統崩潰了。某些有經驗的說我會把下面的try{}catch{}起來,不過那不是脫了褲子放屁麼,異常都拋出來了,開銷已經產生了,結果換來的是犧牲了異常對象的豐富信息而換來了畸形的系統邏輯。性能也沒獲得提升 */ //典型錯誤4 public bool InsertUser(User user,ref int errcode) { if(user==null) { errcode=110;//參數爲空錯誤的代碼 return false; } //調用Orm }
3、異常的性能測試
結論:
一、new Exception() 異常對象和建立普通對象的性能損耗沒太大差異
二、throw 拋出異常時會形成系統性能損耗,主要在於「填充運行的堆棧信息」、「記錄異常快照」等
三、try{}catch{}不會形成明顯的系統開銷,加不加性能區別不大
四、對外提供的方法儘量拋出異常,避免程序崩潰,使用時請繼承ApplicationException基類
五、業務邏輯上的數據儘可能用if{}else{}過濾掉,不要靠throw new Exception()來處理
六、異常在程序中沒法避免,合理使用避免程序崩潰纔是惟一正確的道路
(以上結論僅表明我的觀點)
public class TyhTest { private string msg; public TyhTest(string msg) { this.msg = msg; } } public class TyhException : ApplicationException { //這種寫法是繼承基類構造方法 public TyhException(string msg): base(msg) { } } class Program { static void Main(string[] args) { int max = 100; int j = 1; string str = "a"; //========== Stopwatch time1 = new Stopwatch(); time1.Start(); for (int i = 0; i < max; i++) { try { if (j > 0 && !string.IsNullOrEmpty(str)) throw new Exception("Exception異常"); } catch (Exception e) { } } time1.Stop(); Console.WriteLine("拋出Exception異常耗時:" + time1.ElapsedMilliseconds); //========== Stopwatch time2 = new Stopwatch(); time2.Start(); for (int i = 0; i < max; i++) { try { if (j > 0 && !string.IsNullOrEmpty(str)) throw new ApplicationException("Exception異常"); } catch (ApplicationException e) { } } time2.Stop(); Console.WriteLine("拋出ApplicationException異常耗時:" + time2.ElapsedMilliseconds); //========== Stopwatch time3 = new Stopwatch(); time3.Start(); for (int i = 0; i < max; i++) { try { if (j > 0 && !string.IsNullOrEmpty(str)) throw new TyhException("Exception異常"); } catch (Exception e) { } } time3.Stop(); Console.WriteLine("拋出自定義TyhException異常耗時:" + time3.ElapsedMilliseconds); //========== Stopwatch time4 = new Stopwatch(); time4.Start(); for (int i = 0; i < max; i++) { try { if (j > 0 && !string.IsNullOrEmpty(str)) { } else { } } catch (Exception e) { } } time4.Stop(); Console.WriteLine("不拋異經常使用IF判斷耗時:" + time4.ElapsedMilliseconds); //========== Stopwatch time5 = new Stopwatch(); time5.Start(); for (int i = 0; i < max; i++) { try { var test = new TyhTest("建立對象"); } catch (Exception e) { } } time5.Stop(); Console.WriteLine("建立普通對象TyhTest耗時:" + time5.ElapsedMilliseconds); //========== Stopwatch time6 = new Stopwatch(); time6.Start(); for (int i = 0; i < max; i++) { try { var test = new Exception("建立異常對象"); } catch (Exception e) { } } time6.Stop(); Console.WriteLine("建立異常對象Exception耗時:" + time6.ElapsedMilliseconds); Console.ReadKey(); } }
(Stopwatch 不須要 new 不少個,代碼複製粘貼的,請忽略,忽略,哈哈~)