好的編程習慣受益的是自己
注:本博文面向初學者
前兩天幫QQ群中的一個同學遠程解決一個問題,這個同學據說自己折騰了一天都沒搞定,給他結果以后感想非常多,今天有時間把這個問題以及背后隱藏的問題分享給大家。
下面說的吃異常的錯誤不僅初學者會犯,很多工作很多年的人也經常會犯這種錯誤,因此雖然在很多人看起來很簡單,我還是在這里羅嗦了,希望對有的人有幫助。
這位同學說他寫的程序總是報錯說字段ParentId沒找到,但是數據庫中是有代碼的。他是通過SQLHelper獲得一個DataTable,然后把DataTable展示到ListView中進行數據 展示的。示例性代碼如下:
listview1.DataSource = ds;
listview1.FilterExpression = "ParentId=3";
其實他的這個程序是有很大缺陷的,因為他是在UI層中進行數據過濾的,這個問題暫且不提。
主要問題是,T_Persons表中是有ParentId這個字段的,但是總是報異常“沒有ParentId字段”。
一直讓他很費解,因此我就猜測程序中有被吃掉的異常,因此我在VisualStudio中打開異常檢測,打開主菜單→調試→異常,將Common Language Runtime Exception勾選上,這樣就表示對于捕獲的異常也Break,這樣就可以發現被吃掉的異常了。
程序運行,果然在SQLHelper.ExecuteDataSet調用SqlConnection環節中看到異常拋出了,是“數據庫連接失敗”,示例性代碼如下:
try
{
SqlConnection conn = new SqlConnection(.........);
//...
adapter.Fill(ds);
}
catch
{
}
return ds;
原來是他的連接字符串寫錯了。由于他想“耳根子清凈”,就可恥的把異常給吃掉了,這樣雖然數據庫根本就沒連接上,ExecuteDataSe方法仍然好像啥事都沒發生一樣假模假樣的返回一個空的DataSet,由于這個DataSet什么表結構都沒有,最后報異常“沒有ParentId字段”也就不足為奇。
異常就是一種程序中沒有預料到的問題,既然屬于沒有預料到的,就不應該不想看異常就把所有異常catch吃掉,本來ExecuteDataSet執行數據庫操作已經失敗了,后續的代碼也就沒有意義了,不應該繼續執行了,應該讓用戶或者開發人員知道“這里出錯了”,而不是繼續掩耳盜鈴的執行下去,否則很容易造成程序進入一個邏輯混亂的狀態,出現各種奇怪的問題。
第二季:《C#面向對象基礎》這個視頻教程中也提到了,異常是C#中提供的一個比以前錯誤碼機制更好的一種錯誤處理機制,如果這么討厭異常還不如回到錯誤碼的時代更清凈呢,在錯誤碼時代只要不出現“Access Violation”,管它程序邏輯是不是有問題,都可以一直"耳根清凈的執行下去",可是你希望這樣嗎?
對于有的情況確實需要catch異常的地方,只要不是處理后重新拋出,也最好將異常通過Log4Net等日志工具記錄下來,方便開發人員排查問題。
有人說程序一旦出現異常多難看呀?“客戶看到一堆異常的英文界面就發怒,還是吃了好呀”,其實不要吃異常和不讓用戶看到“一堆異常的英文界面”并不沖突,比如在ASP.Net中就可以通過定制錯誤頁的方式來解決,將錯誤頁顯示的模式設置為“RemoteOnly”,這樣普通用戶看的是定制后的沒有“一堆異常的英文界面”的頁面,而對于開發人員和系統管理員看到的則還是異常頁面,“兩不耽誤”!
“不要吃異常”、“不要使用魔法數”、“資源最好用using進行管理”等這些非常常見的好的編程習慣是最容易被初學者忽略的,最終不遵守好習慣而自食其果的例子也屢見不鮮,建議大家要認真遵守這些基本的原則,最終受益的仍然是自己。