下面本小结重点讲异常处理语句
Try-catch 语句包含一个后接一个或多个 catch
子句的 try
块,这些子句指定不同异常的处理程序。
引发异常时,公共语言运行时 (CLR) 查找处理此异常的 catch
语句。 如果当前正在执行的方法不包含此类 catch
块,则 CLR 查看调用了当前方法的方法,并以此类推遍历调用堆栈。 如果未找到任何 catch
块,则 CLR 向用户显示一条未处理的异常消息,并停止执行程序。
try
块包含可能导致异常的受保护的代码。 将执行此块,直至引发异常或其成功完成。 例如,强制转换 null
对象的以下尝试会引发 NullReferenceException 异常:
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
尽管可以不带参数使用 catch
子句来捕获任何类型的异常,但不推荐这种用法。 一般情况下,只应捕获你知道如何从其恢复的异常。 因此,应始终指定派生自 System.Exception 的对象参数,例如:
catch (InvalidCastException e)
{
}
可以使用同一 try-catch 语句中的多个特定 catch
子句。 在这种情况下,catch
子句的顺序很重要,因为 catch
子句是按顺序检查的。 在使用更笼统的子句之前获取特定性更强的异常。 如果捕获块的排序使得永不会达到之后的块,则编译器将产生错误。
发出程序执行期间出现异常的信号。
语法为:throw [e]
e
是一个派生自 System.Exception 的类的实例。 下例使用 throw
语句在传递给名为 GetNumber
的方法的参数与内部数组的有效索引不对应时引发 IndexOutOfRangeException 。
using System;
namespace Throw2
{
public class NumberGenerator
{
int[] numbers = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
public int GetNumber(int index)
{
if (index < 0 || index >= numbers.Length)
{
throw new IndexOutOfRangeException();
}
return numbers[index];
}
}
然后方法调用方使用 try-catch
或 try-catch-finally
块来处理引发的异常。 下例处理由 GetNumber
方法引发的异常。
using System;
public class Example
{
public static void Main()
{
var gen = new NumberGenerator();
int index = 10;
try
{
int value = gen.GetNumber(index);
Console.WriteLine($"Retrieved {value}");
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine($"{e.GetType().Name}: {index} is outside the bounds of the array");
}
}
}
// The example displays the following output:
// IndexOutOfRangeException: 10 is outside the bounds of the array
throw
也可以用于 catch
块,以重新引发在 catch
块中处理的异常。
从 C# 7.0 开始,throw
可以用作表达式和语句。 这允许在以前不支持的上下文中引发异常。 这些方法包括:
private static void DisplayFirstNumber(string[] args)
{
string arg = args.Length >= 1 ? args[0] :
throw new ArgumentException("You must supply an argument");
if (Int64.TryParse(arg, out var number))
Console.WriteLine($"You entered {number:F0}");
else
Console.WriteLine($"{arg} is not a number.");
}
public string Name
{
get => name;
set => name = value ??
throw new ArgumentNullException(paramName: nameof(value), message: "Name cannot be null");
}
DateTime ToDateTime(IFormatProvider provider) =>
throw new InvalidCastException("Conversion to a DateTime is not supported.");