星期六 十二月 12, 2009 19:00
cSharp中异常处理的笔记
停了几天的笔记。感觉学习的内容要么像反射(Reflection in .net framework)一样高深,想写点笔记却怎么也写不上;要么学习的内容(像集合、泛型,泛型集合、Language Integrated Querry)太细太杂,可写的太多,想记都记不过来。看到了.net 中的异常处理,总算,让我开始有点想法了。我总结了下面的几个问题:
1.执行多个catch 块,讲究一个顺序:从最特殊到最一般。下面的代码是我写的一个demo,模拟了3种异常:一种是用户的输入超过了规定值后,抛出了一个IndexOutOfRangeException,另一种是很普适的System.Exception,最后一种是不带参数的catch,它可以处理非托管堆上的代码异常(包括非c# 的代码)。以这样的顺序布局,才能够细致的捕获到各个可能出现的问题。但,如果将System.Exception 的catch 放到最前面,编译器就会报错:“上一个 catch 子句已经捕获了此类型或超类型(“System.Exception”)的所有异常”,因为IndexOutOfRangeException是从System.Exception 里继承过来的。当然要体会这样布局的真正优势,需要一些彪悍的异常处理方法,而不是一个简单的Writeline().
public static void Main()
{
int aNum;
Console.WriteLine("Input a number between 1 and 5:");
string userInput = Console.ReadLine();
try
{
aNum = Int32.Parse(userInput);
if (aNum<1 || aNum> 5)
throw new System.IndexOutOfRangeException("You type :" + userInput);
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("Number should be between 1 and 5. But " + e.Message);
}
catch (Exception e)
{
Console.WriteLine("An Exception in Managed Heap thrown by .net framework :" + e.Message);
}
catch
{
Console.WriteLine("An Exception in Unmanaged heap thrown by the .net framework!");
}
finally {
Console.WriteLine("Thank you!");
}
}
}
另外,这个代码在编译的时候会有一个警告:”上一个 catch 子句已捕获所有异常。引发的所有非异常均被包装在 System.Runtime.CompilerServices.RuntimeWrappedException 中。 “这个是因为本代码中根本就不包含非c# 的代码,出现的异常都在托管堆中发生。事实上这个代码的工作频率并不大,这里写上只是为了说明这个规则。
2.修改异常类型。在上面的demo 中,如果用户没有输入一个数字而是字母或者是数字和字母的组合,那么将会看到:”An Exception in Managed Heap thrown by .net framework :输入字符串的格式不正确。“我们知道错误是发生在Int32.Parse()这个方法里。但Exception 给出的提示信息不太符合咱们的思维,并且从安全的角度来说,它甚至有可能暴露程序的某些底层问题。因此修改异常类型迫在眉睫!
3.设计异常中间类型。一段代码,可能异常处理集中在一堆里,但细节各不相同。为了使得整体的规律性,以及代码的便于管理,可以在这里给出一个继承于System.ApplicationException 的中间类,如MethodException。细致的处理异常,可以继续继承于MethodException,如OutOfRangeInMethodException,NotSupportMethodException等来处理各种不同的异常,这样就解决了第2点中提到的问题。
4.嵌套的try-catch块。我想还是代码最能说明问题:
try {
//point A
try
{
//point B
}
catch {
//point C
}
finally {
//point D
}
}
catch {
//Error hanling
}
finally {
//clean up
}
这里没有处理什么问题,只是将2个嵌套的try-catch 块进行了一个大致的区域划分。
- 当异常在point A、或者point D 中爆发,问题很简单,将由外层的catch 来捕获;
- 当异常在point A、或者point D 中爆发,而问题不太简单的时候,外层catch 无法捕获时,由.net framework 的隐藏try-catch 来捕获。
- 当异常在point B 中爆发,问题很简单,将由内层catch 来捕获;
- 当异常在point B 中爆发,而问题不太简单的时候,跳出内层try-catch 块,执行内层finally 块,问题变为在point A或者point D 爆发异常。
- 当异常在point C 中爆发,则会执行爆发C 异常之前的处理B的代码,而后退出内层try-catch 块,执行内层finally 块,问题变为在point A或者point D 爆发异常。
多少个try-catch 都不是问题,这个例子只说明了嵌套try-catch 块的工作方式。开水房要关门了,我去打水先…
- Category: csharp-note
- (1) Comment
开心凡人
十二月 12th, 2009 at 10:57 下午
周末到处看一看,这里挺好呵呵