异常提供了一种结构化的错误处理机制,使得错误检测和处理可以和正常的程序逻辑分离。使用异常有以下优点:
finally
块或者using
语句块,可以确保即使在发生错误的情况下,也能释放资源,如文件句柄、网络连接、数据库连接等。.NET中的异常有很多,但这里列出了一些最常见的异常类型:
System.Exception
派生的用于系统异常的基类。null
时抛出。使用异常处理机制时,很重要的一点是只处理那些你确实可以处理的异常情况,避免捕获太广泛的异常类型,这可能会掩盖一些应当被发现的错误。
在.NET Framework中,异常处理是通过使用一组关键字(try
、catch
、finally
和 throw
)在运行时对错误进行检测和处理的一种方式。异常处理架构是基于下面几个核心概念设计的:
System.Exception 基类
所有异常都派生自System.Exception
类。这个基类提供了几个重要的属性,如Message
、StackTrace
、InnerException
等,这些属性给出了关于异常的详细信息。
.NET Framework定义了一个异常类的层次结构,这样就可以通过捕获特定类型的异常来对不同的错误条件作出响应。例如,System.IO.IOException
是处理与输入/输出操作相关的异常,而System.IndexOutOfRangeException
用于处理访问数组时索引超出其界限的情况。
try
块用于定义可能会引发异常的代码段。如果在try
块中的代码抛出异常,控制流将跳转到后续的catch
块。
catch
块跟在try
块后面,并定义了一系列的异常处理程序。每个catch
块针对一个特定的异常类型(或所有异常,如果没有指定类型)。当异常被抛出时,运行时会查找匹配的catch
块来处理它。
我们可以有多个catch
块来捕获不同类型的异常,它们应该从最具体到最一般的顺序排列。
finally
块是可选的,用于执行无论是否发生异常都需要执行的清理代码。即使try
或catch
块中有return
语句,finally
块中的代码也会执行。
throw
关键字用于抛出异常。你可以重新抛出当前处理的异常,或者抛出一个新的异常实例。
以下是一个C#中使用异常处理的简单示例:
try
{
// 试图执行可能会抛出异常的代码
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers[3]); // 这将引发IndexOutOfRangeException(异常类型,这种异常在尝试访问数组、集合或列表等类型的元素时,如果使用的索引超出了实际的范围,就会被抛出。)
}
catch (IndexOutOfRangeException ex)
{
// 捕获并处理特定类型的异常
Console.WriteLine("An index out of range exception occurred: " + ex.Message);
}
catch (Exception ex)
{
// 捕获并处理所有其他类型的异常
Console.WriteLine("An unexpected error occurred: " + ex.Message);
}
finally
{
// 清理代码,在这里执行
Console.WriteLine("The 'try catch' block is finished.");
}
在这个例子中,如果访问数组的索引超出了范围,将会触发IndexOutOfRangeException
,这个异常会被第一个catch
块捕获并处理。finally
块中的代码无论是否发生异常都会执行,用于执行清理工作。如果异常类型不匹配IndexOutOfRangeException
,那么会被第二个catch
块捕获。
精确捕获:
catch
。避免空的catch块:
使用finally释放资源:
finally
块确保即使发生异常也能够释放资源。异常具体化:
不要用异常控制流程:
最小化try块的代码量:
try
块中应该只包含可能抛出异常的代码,这有助于减少错误发生的范围,并使 try-catch
结构更清晰。抛出正确的异常类型:
保守的catch:
System.Exception
或 System.SystemException
,应该避免。