.Net中Exception你這樣做了么?
這篇文章旨在與園友分享我對Exception的理解,如果存在不足的地方歡迎您指出。
前不久寫過一篇MVC的Exception的文章,這回重點講解在實際開發中我對Exception 的認識。
講到Exception難免會涉及到經典的代碼try..catch...finally..至于一些基本概念:這個代碼塊的執行方式、多catch的異常捕獲順序、exception的繼承。這些不是本篇討論的重點,但這不并代表基本概念不重要。
建立Exception 時建議日常開發中需要注意以下幾點:
一、Throw new exception
曾經看過有人在簡單的函數內瘋狂的使用throw new 參與業務邏輯。比如,以下代碼:
{
try
{
if (String.IsNullOrEmpty(userName))
{
throw new Exception("用戶名不能為空");
}
}
catch (Exception ex)
{
return ex.Message;
}
return true;
}
邏輯類似以上代碼,就是一個單一的函數,每當我看到這樣的單一函數,總是覺得很奇怪。或許是自身水平有限,似乎難以理解為了catch住一個exception對象需要那么大費周章的去throw new 么?個人認為如果某方法內嵌套的方法根據業務邏輯主動拋出異常,讓外層方法截獲到這個異常,此時被嵌套的方法方可使用throw new ....
二、拋出不該拋出的Exception
上文中的DoSomeThing函數如果在catch時不進一步封裝,直接把Excepiton拋到UI層,又或者直接顯示給客戶。如果異常堆棧中提示某些敏感數據。比如SQL查詢語句、WebService URI或POST信息等。這些敏感信息應該永遠不讓客戶知道,暴露出這些信息有可能對系統造成潛在安全隱患!
三、更好的利用Exception
在實際的開發中,既然拋出了Exception那么我們應該為Exception提供盡可能多的關于異常本身的有用信息。如何為拋出的異常提供更多的有用信息呢?請看以下代碼:
{
using (var connection = new SqlConnection("數據庫連接字符串"))
{
var cmd = connection.CreateCommand();
try
{
action(cmd);
cmd.ExecuteNonQuery();
}
catch (DbException ex) //注意這里將DbException catch住
{
errMsg = ex.Message;
var parameters = new Dictionary<string, object>();
foreach (SqlParameter p in cmd.Parameters)
parameters.Add(p.ParameterName, p.Value);
//盡可能獲取與exception相關的有用信息,這里只是用SqlParameter舉例而已。
//TODO:(將 parameters 與 ex 對象保存或者進一步處理)
}
catch (Exception ex)
{
//TODO 其他的異常處理
}
finally
{
cmd.Dispose();
}
}
}
注釋已經給的很清晰了,目的就是盡可能的提供與異常相關的有用信息,方便日后異常出現時便于調試。
ExecuteCommand方法調用如下:
{
string errMsg = string.Empty;
ExecuteCommand(cmd =>
{
cmd.CommandText = "UPDATE user SET name=@name WHERE id=@id";
cmd.Parameters.Add(new SqlParameter("name", "字符串參數值"));
cmd.Parameters.Add(new SqlParameter("id", 1));
}, ref errMsg);
}
類似以上機制,如果異常出現了,我認為可以大大減少debug的時間。