C#2008与.NET 3.5 高级程序设计读书笔记(7)--结构化异常处理
1.如何处理异常
作为一个开发人员,你应该感受到通过try, catch, finally块来构建一个结构化异常处理机制的优点。.NET框架提供了一大堆异常处理层次来处理不同种类的异常。所有的异常都继承自Exception(基类)。你可以通过继承来实现自定义错误处理以扩展异常处理机制。不幸的是,很多开发人员都误用了这种架构能力。一个随时要记着的事是当一个异常发生在运行时时(这个架构)应该如何运作?一般有以下三种情况:
- 忽略异常,让它在调用栈里上升而被其它的catch块捕获。
- 捕获异常,同时为你的应用程序执行必要的动作,如果你不想再次在异常中抛出异常的话。
- 捕获异常,并用其它异常覆盖它。这样和你的应用程序有更密切的关系。异常覆盖是为了避免打破(架构中的)抽象层次。你可以通过你抛出的异常的InnerException属性指定原异常是什么,这样就可以把你现有的异常用一个新的异常来覆盖了(更与你系统有关的)。为了了解异常覆盖,让我们来看一个能引起IOException异常的方法,你可以在应用级别使用LoadingException 或 FailtoLoadInfoException来覆盖原有的IOException异常,这样比把底层的IOException给用户看到要来的好些。
经验总结:
尽可能在最低级别处理错误。
避免通过异常处理机制将较低级别(DataAccess,Facade)抽象公开给较高级别(UI)。
如果您必须使异常沿栈上移,那么应将较低级别异常转化为对于处理层而言有一定意义的异常(自定义异常)。
2.System.Exception成员
3.构建自定义异常
什么时候需要构建自定义异常呢?通常情况下,仅需在出现错误的类与该错误关系紧密时才需要创建只定义异常.例如,一个自定义文件类引发许多文件相关的错误.一个Car类引发许多汽车相关的错误.
4.代码例子
采用标准try/catch/finally异常处理方式进行处理,这在托管代码里是被推荐的。最后的Finally块确保异常事件中的资源都被释放掉了。
代码
SqlConnection conn = new SqlConnection("");
try
{
conn.Open();
// some operation
// some additional operations
}
catch(Exception ex)
{
// handle the exception
}
finally
{
if (conn != null && conn.State == ConnectionState.Open)
conn.Close(); // closing the connection
}
逐级处理异常
try
{
}
catch(SqlException sqlexp) // specific exception handler
{
}
catch(Exception ex) // Generic exception handler
{
}