6.4
抛出异常假定你要实现一个名为monthNamee(月份名称)的方法,它接收一个int参数,并返回对应月份的名称。例如,monthName(l)应返回”January”,monthName(2)应返回“February”。现在的问题是:如果传递的整数实参小于l或人于12.方法应返回什么?最好的答案是方法不应返回任何东西:它应该抛出个异常。.NET Framework类库包含专门为这种情况设计的众多异常类。人多数时候,都能从中找到一个与自己要求决的异常情况对应的类(否则,也很容易创建自己的异常类。但在此之前,需要更多地学习一下C#语言)。在本例中,.NETFramework的ArgumentOutOfRangeException类刚好满足我们的需要,如下所示
public static string monthMame(int month)
{
switch(month)
{
case 1:
return “January”;
case 2:
return “February”;
case 12:
return “December”;
default:
throw new ArgumentOutOfRangeException("不存在的月份");
}
}
注意,在default情况下,使用一个throw语句来抛出异常。throw语句要抛出一个异常对象。在本例中,我们使用一个表达式来创建一个新的ArgumentOutOfRangeExceptian对象。这个对象使用一个字符串来进行了初始化,该字符串将在一个构造函数的帮助下填充对象的Message属性。构造函数的详情将在第7章讲述。在下面的练习中,我们将在MathsOperators项目中添加一些代码来抛出一个异常。
》
抛出异常示例l,返回Visual Studio 2008编程环境。
2,在“调试”菜单中选择“开始执行(不调试)”。
3,在left operand文本框中输入24,在right operand文本框中输入36,单击Calculate按钮。Result文本框中将显示值0。如果不仔细检查,你恐怕还不知道自己尚未选择一个操作符。由此看来,有必要在Result文本框中输出一条诊断消息,清楚地提醒用户尚未选择操作符这一事实。
4,单击Quit按钮,返回Visual Studio 2008编程环境。
5,在“代码和文本编辑器”窗口显示Windowl.xaml.cs的代码,找到并检查doCalculation方法。该方法如下所示:
addition,subtraction,multiplication,division和remamder代表窗体上显示的各个单选按钮。每个单选按钮都有一个名为IsChecked的属性.指出用户是否已经选定它。isChecked属性是可空(nullable)值的一个例子;换言之,它要么包含一个具体的值,要么处于一个未定义的状态(可空值的详情请参见第8章)。IsChecked.HasValue属性指出单选按钮是否处于已定义状态;如果是,IsChecked.Value属性就指出具体是什么状态。IsChecked.Value属性是一个布尔值:如果单选按钮被选定,则值为true,反之为false。层叠的if语句将依次检查每个单选按钮,判断具体哪一个被选中。(单选按钮是互斥的,用户一次只能选中其中的一个。)如果没有任何单选按钮被选中,就没有任何if语句的条件为turue,result变量将保持它的初始值(0)。result变量的值就是方法的返回值。 为了处理用户可能没有选择任何单选按钮的情况,可以在if-else结构中再添加一个else语句,以便在发生这种情况时向result文本框输出一条消息。然而,这并不是一个好的做法,因为该方法(doCalculation)的真正目的并不是输出消息。更好的做法是将检测通知错误发生的代码与捕捉,处理错误的代码分开。
6,在if-else结构中再添加一个else语句(把它放到return语句之前),它将抛出一个 InvalidOperationException异常。如下所示:
else
throw new InvalidOperationException("no operator selected");
7,在“调试”菜单中选择“开始执行(不调试)”,生成并运行应用程序。
8,在left operand文本框中输入24.在right operand文本框中输入36,单击Calculate按钮随后会弹出一个异常对话框。虽然应用程序能抛出异常,但代码尚未捕捉它。
9,单击“关闭程序”。应用程序终止运行,并返回Visual Studi0 2008编程环境。
前面已经写了一个throw语句,并证实它能抛出一个异常.接着写一个catch处理程序捕捉这个异常。
》捕捉自己的异常
1,在“代码和文本编辑器”窗口显示Windowl.xaml.cs的源代码,找到calculateClick方法。
2,在calculateClick方法现有的两个catch处理程序之后,添加以下catch处理程序:
cathc(InvalidOperationException ioEx)
{
result.Text=ioEx.Message;
}
这段代码将捕捉InvalidOperationException异常。如果用户没有选择任何操作符,单击Calculate按钮就会抛出此异常。
3,在“调试”菜单中选择“开始执行(不调试)”,生成并运行应用程序。
4,在leftoperand文本框中输入24,在right operand文本框中输入36,单击Calculate按钮Result文本框中将正确显示提示消息:“no operator selected”。
5,单击Quit按钮。
和以前相比,这个应用程序的可靠性已经大幅提高了。然而,仍有几个可能发生的异常未被捕捉,它们会造成应用程序执行失败。例如,假如试图除以0,就会抛出一个未处理的DivideByZeroException(用0来除一个整数会抛出异常,但用0来除—个浮点数不会抛出异常)。为了解决这个问题,一个办法是在calculateClick方法内添加更多的catch处理程序。然而,一个更好的解决方案是在catch处理程序列表的末尾添加一个常规catch处理程序来捕捉Exception。这样就可以捕捉一切未处理的异常。
提示:具体是否需要在一个方法内部显式地捕捉所有未处理的异常,取决于所设计的应用程序的本质。某些时候,有必要在尽量靠近异常抛出点的地方捕捉它,但在另一些时候,更好的做法是让异常顺着方法调用堆栈传回,由外层的方法来处理异常。
》
捕捉未处理的异常l,在“代码和文本编辑器”窗口显示Windowl.xaml.cs的源代码,找到calculateClick方法。
2,在现有的一系列catch处理程序的末尾,添加以下常规catch处理程序:
catch (Exception ex)
这个catch处理程序将捕捉在它之前所有未处理的异常,不管异常具体是什么类型。
3,在“调试”菜单中选择“开始执行(不调试)”。
接着.让我们来尝试一些已知会造成异常的计算,确定它们都会被捕捉到。
4,在left operand文本框中输入24.在right operand文本框中输入36,单击Calculate按钮。确定Result文本框中显示的诊断消息仍然是:“no operator selected”。该消息是由InvalidOperationException处理程序生成的。
5,在left operand文本框中输入John,单击Calculate按钮。确定Result文本框中显示的诊断消息仍然是:“输入字符串的格式不正确。”该消息是由FormatException处理程序生成的。
6,在left operand文本框中输入24,在right operand文本框中输入0,在操作符区域选择“/Divide”选项,单击Calculale按钮。确定Result文本框中显示的诊断消息是:“试图除以0。”该消息是由刚才添加的常规异常处理程序生成的。
7,单击Quit按钮。