第六章 管理错误和异常
1.多个catch
try
{
......
}
catch(FormatException f)
{
......
}
catch(OverflowException o)
{
......
//这里抛出FormatException,该异常会传递给调用栈的上一级
}
2.捕捉多个异常
如何保证所有可能的异常都被捕捉并处理?
这个问题的关键在于各个异常之间的关系。异常用继承层次结构进行组织。
FormatException和OverflowException异常都属于SystemException家族。该家族还包含其它许多异常。
SystemException本身又是Exception家族的成员,而Exception是所有异常的"老祖宗"。
捕捉Exception相当于捕捉所有可能发生的异常。
try
{
.....
//这里抛出FormatException,最终运行哪一个?
//异常发生后将运行由 “运行时” 发现的第一个匹配的异常处理程序,其它处理程序会被忽略。
}
catch(FormatException f)
{}
catch(Exception e)
{}
3.筛选异常
用when关键字加一个布尔表达式,可筛选与catch处理程序匹配的异常,确保异常处理程序仅在满足额外的条件时才促发。
bool isConnect = ...;
try
{
....
}
catch(Exception e) when (isConnect)
{
//仅在isConnect为true时才处理异常
}
4.使用checked和unchecked整数运算
checked语句是以checked关键字开头的代码块。checked语句中的任何整数运算溢出都抛出OverflowException异常。
int number = int.MaxValue;
checked
{
int number = 1;
Calculate(1);//只有直接在checked块中的整数运算才会检查。对于块中的方法调用,不会检查所调用方法中的整数运算
}
int Calculate(int num)
{
int willThrow;
checked
{
willThrow = number + num;// checked关键字检查算数溢出。number++求值后已经溢出,所以会抛出OverflowException
Console.WriteLine($"{number}"); // 永远都执行不到这里
}
return willThrow
}
unchecked则不检查算术溢出,不会抛出OverflowException。
也可以在项目属性来启用或禁用溢出检查。右击项目 -> (最底部) 属性 -> 生成 -> (最底部) 高级-> 检查算数溢出
5.使用finally
抛出异常会改变程序的执行流程。
当catch处理程序运行完毕,会从整个try/catch块之后的语句继续,而不是从抛出异常的语句之后继续。
int number = int.MaxValue;
try
{
long storage;
checked
{
storage = number++;//算术溢出,抛出OverflowException。
}
//下面的代码将不会被执行!
Console.WriteLine("aaaaaa");
Console.WriteLine("bbbbbb");
Console.WriteLine("cccccc");
Console.WriteLine($"{storage}");
}
catch (OverflowException o)
{
//处理捕获的算术溢出异常。执行完毕后将向下执行,不会返回抛出异常位置处继续执行!
Console.WriteLine($"{o.Message}"); ;
}
Console.WriteLine("ddddddd");
抛出异常,导致有些语句无法运行,解决方案是写一个finally语句块,放到其中的语句总是运行。
Devide(2,0); // 没有写捕获异常的处理程序,程序将报错退出。
......
int Devide(int first, int second)
{
int result = 0;
try
{
result = first / devide; // 被除数为0,抛出devideByZeroException。
} //没有匹配的catch语句块,
finally
{
//首先运行finally块,再返回上一级搜索匹配的处理程序。
Console.WriteLine("算术语句异常");
}
}
```

浙公网安备 33010602011771号