C#异常处理中try和catch语句及finally语句的用法示例
使用try/catch处理异常
try-catch块的用途是捕捉和处理工作代码所生成的异常。有些异常可以在catch块中处理,解决问题后不会再次引发异常;但更多情况下,您唯一能做的是确保引发适当的异常。
示例
在此示例中,IndexOutOfRangeException不是最适当的异常:对本方法而言ArgumentOutOfRangeException更恰当些,因为错误是由调用方传入的index参数导致的。
classTestTryCatch { staticintGetInt(int[]array,intindex) { try { returnarray[index]; } catch(System.IndexOutOfRangeExceptione)//CS0168 { System.Console.WriteLine(e.Message); //SetIndexOutOfRangeExceptiontothenewexception'sInnerException. thrownewSystem.ArgumentOutOfRangeException("indexparameterisoutofrange.",e); } } }
注释
导致异常的代码被括在try块中。在其后面紧接着添加一个catch语句,以便在IndexOutOfRangeException发生时对其进行处理。catch块处理IndexOutOfRangeException,并引发更适当的ArgumentOutOfRangeException异常。为给调用方提供尽可能多的信息,应考虑将原始异常指定为新异常的InnerException。因为InnerException属性是只读,所以必须在新异常的构造函数中为其赋值。
使用finally执行清理代码
finally语句的目的是确保即使在引发异常的情况下也能立即进行必要的对象(通常是保存外部资源的对象)清理。此类清理功能的一个示例是在使用后立即对FileStream调用Close,而不是等待公共语言运行时对该对象进行垃圾回收,如下所示:
staticvoidCodeWithoutCleanup() { System.IO.FileStreamfile=null; System.IO.FileInfofileInfo=newSystem.IO.FileInfo("C:\\file.txt"); file=fileInfo.OpenWrite(); file.WriteByte(0xF); file.Close(); }
为了将上面的代码转换为try-catch-finally语句,需要将清理代码与工作代码分开,如下所示。
staticvoidCodeWithCleanup() { System.IO.FileStreamfile=null; System.IO.FileInfofileInfo=null; try { fileInfo=newSystem.IO.FileInfo("C:\\file.txt"); file=fileInfo.OpenWrite(); file.WriteByte(0xF); } catch(System.UnauthorizedAccessExceptione) { System.Console.WriteLine(e.Message); } finally { if(file!=null) { file.Close(); } } }
因为在OpenWrite()调用前,try块内随时都有可能发生异常,OpenWrite()调用本身也有可能失败,所以我们无法保证该文件在我们尝试关闭它时处于打开状态。finally块添加了一项检查,以确保在调用Close方法前,FileStream对象不为null。如果没有null检查,finally块可能引发自身的NullReferenceException,但是应当尽可能避免在finally块中引发异常。
在finally块中关闭数据库连接是另一个不错的选择。因为有时候数据库服务器允许的连接数是有限的,所以应尽快关闭数据库连接。在由于引发了异常而无法关闭连接的情况下,使用finally块也是比等待垃圾回收更好的一种选择。