代码改变世界

《C#本质论》读书笔记(十)异常处理 @ Lennon

2010-07-28 11:56  张抗  阅读(1313)  评论(3)    收藏  举报

        C#中捕获错误信息通过try-catch-finally实现捕获错误信息。

 

代码
try
{
AdjustPhoto(
0);

if (Convert.ToInt32(txtRed.Text) > 255)
tbRed.Value
= 255;
else
tbRed.Value
= Convert.ToInt32(txtRed.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{
MessageBox.Show(
"");
}

        try-catch-finally作用

 

        try块里的代码是要来检测的代码,有可能引发一个异常。如果真的引发了异常,那么某个catch块就要尝试处理这个异常,可以同时存在多个catch块,用来捕获不同的错误信息。而finally块的作用是提供一个最终位置,在其中放入无论是否发生异常都要执行的代码。finally块最适合用来执行资源清理。无论try块中的代码是否引发一个异常,finally块都会执行。

         Exception类和派生类

         System.Exception类是所有异常类的基类,所以,可以直接用catch(Exception ex)来捕获异常信息,但为了捕获有关异常的具体信息,我们用更具体的派生类型来处理错误。

         C#中如果同时存在多个catch块,为了捕获具体的异常信息,必须从“最具体”到“最不具体”排列。也就是说,用于捕获Exception的catch语句不能出现在捕获FormatException的catch语句之前,因为FormatException比Exception更为具体。

        

Exception 应用程序执行期间发生错误  
SystemException 系统异常 所有Exception的基类
ArgumentException 当方法提供的任意一个参数无效时,引发此异常  
ArithmeticException 算数导致的错误  
DataException 在使用ADO.NET组件时生成错误 System.Data命名空间提供
FormatException 参数的格式不符合被调用方法的参数规范  
IOException IO错误 System.IO命名空间提供
IndexOutOfRangeException 数组越界  
ArgumentNullException 空引用传递给无效参数的方法时引发 对应JAVA的空指针
DivideByZeroException 0为除数  
OverflowException 运算结果过大,无法以目标格式保存 比如把一个30位数字赋给int
ApplicationException 应用程序执行过程中检测到由应用程序定义的异常  
TargetException 试图调用无效目标时 System.Reflection命名空间提供

 

         什么是泛化catch?

         没有指定数据类型的catch块称为泛化catch块,它等价于获取object数据类型的catch块。没有数据类型的catch块必须出现在最后。

         泛化catch作用?

         C# 2.0中的行为稍微有别于之前版本的C#。在C# 2.0中,假如遇到用另一种语言写的代码,而且它会引发不是从System.Exception类派生的异常,那么该异常对象会被包装到一个System. Runtime.CompilerServices.RuntimeWrappedException中,后者是从System.Exception派生的。换言之,在C#程序集中,所有异常(无论它们是否从System.Exception派生)都会表现得和从System.Exception派生一样。 

         结果就是,用于捕捉System.Exception的catch块会捕捉之前的块没有捕捉到的所有异常, 同时,System.Exception catch块之后的一个常规catch块永远得不到调用。所以,在C# 2.0中,假如在捕捉System.Exception的catch块之后添加了一个常规catch块,编译器就会报告一条警告消息,指出常规catch块永远都不会执行。

        使用throw语句报告错误

        一个catch块可以捕获到一个异常,但不能正确或者完整地处理它。在这种情况下,可以让这个catch块重新引发异常,具体的办法是使用一个单独的throw语句,不要在它后面指定任何异常

        

。。。
catch(Exception ex)
{
Console.WriteLine(
"Rethrowing unexpected error: {0}",ex.Message);
throw;//单独的Throw
}
。。。

 

         避免使用异常处理来处理预料之中的情况

         和大多数语言一样,在C#中引发一个异常,会对性能造成不利影响,尤其是在负责错误处理的基础结构第一次加载的时候。由于引发异常会引发性能问题,所以开发者应当尽量避免为预料之中的情况或者正常的控制流引发异常。不要用异常来验证用户输入的数据。相反,开发者应该在尝试转换之前对数据进行检查,甚至可以考虑从一开始就防止用户输入无效的数据。

         总之,一句话。一个良好的程序尽量避免少使用try-catch-finally。