使用throw语句报告错误

来源:百度文库 编辑:神马文学网 时间:2024/04/27 14:16:13

4.8.2 使用throw语句报告错误
就像int.Parse()能引发一个异常一样,C#允许开发者从他们的代码中引发异常,代码清单4-21和输出4-15对此进行了演示。
代码清单4-21 引发一个异常
using System; class ThrowingExceptions
{
static void Main()
{
try
{
Console.WriteLine("Begin executing");
Console.WriteLine("Throw execution...");
throw new Exception("Arbitrary exception");
Console.WriteLine("End executing");
}
catch (FormatException exception)
{
Console.WriteLine(
"A FormatException was thrown");
}
catch(Exception exception)
{
Console.WriteLine(
"Unexpected error: {0}", exception.Message);
}
catch
{
Console.WriteLine("Unexpected error!");
}       Console.WriteLine(
"Shutting down...");
}
}
输出4-15
Begin executing
Throw exception...
Unexpected error: Arbitrary exception
Shutting down...
如代码清单4-21中的箭头所示,如果引发一个异常,会使执行从异常的引发点跳转到与引发的异常类型兼容的第一个catch块。在本例中,是第二个catch块处理引发的异常,它在屏幕上输出一条错误消息。这个程序没有finally块,所以它随后会执行try/catch块之后的System.Console. WriteLine()语句。
为了引发异常,需要有Exception的实例。代码清单4-21使用关键字new,后跟异常的数据类型,从而创建了这样的一个实例。大多数异常类型都允许在引发该类型的一个实例时传递一条消息,以便在发生异常的时候,获取与具体发生的异常有关的消息。
有的时候,一个catch块可以捕捉到一个异常,但不能正确或者完整地处理它。在这种情况下,可以让这个catch块重新引发异常,具体的办法是使用一个单独的throw语句,不要在它后面指定任何异常,如代码清单4-22所示。
代码清单4-22 重新引发一个异常
...
catch(Exception exception)
{
Console.WriteLine(
"Rethrowing unexpected error: {0}",
exception.Message);
throw;
}
...
避免使用异常处理来处理预料之中的情况
和大多数语言一样,在C#中引发一个异常,会对性能造成不利影响,尤其是在负责错误处理的基础结构第一次加载的时候。例如,运行代码清单4-18的程序,并输入一个无效的年龄,你会感到一阵明显的停顿,这正是由程序引发和处理异常造成的。由于引发异常会引发性能问题,所以开发者应当尽量避免为预料之中的情况或者正常的控制流引发异常。例如,开发者事先就应该预料到用户可能在输入年龄的时候输入无效的文本。所以,不要用异常来验证用户输入的数据。相反,开发者应该在尝试转换之前对数据进行检查,甚至可以考虑从一开始就防止用户输入无效的数据。
高级主题:使用TryParse()来执行数值转换
Parse()方法的一个问题在于,要知道转换能否成功,唯一的办法就是尝试执行类型转换,并在发现失败的时候引发并捕捉异常。因为异常处理的代价相当高,所以更好的办法是尝试执行转换,同时不进行异常处理。在C#的第一个版本中,唯一支持这样做的是一个double类型的方法,名为double.TryParse()。然而,在CLI2.0版本中,CLI为所有基本数值类型都实现了这个方法。它要求使用out关键字,因为从TryParse()返回的是一个bool值,而不是转换好的值。以下代码演示了如何使用int.TryParse()来尝试转换:
...
if (int.TryParse(ageText, out age))
{
System.Console.WriteLine(
"Hi {0}! You are {1} months old.", firstName,
age * 12);
}
else
{
System.Console.WriteLine(
"The age entered ,{0}, is not valid.", ageText);
}
...
有了TryParse()方法的帮助,就不会仅仅为了处理从字符串向数值的转换就动用一个try/ catch块了。