.NET之所以选择异常,而不是返回错误码来报告异常,是由于前者有以下几个优势:
1、异常与oop语言的结合性更好。oop语言经常需要对成员签名强加限制,比如c#中的构造函数、操作符重载和属性,开发者对成员签名中的返回值没有选择余地,故想在oop中统一使用错误码来报告错误是不现实的,替代方案就是在这些特殊场景下使用错误码之外的错误报告机制,比如异常。这样一来,问题就转变为了是否应该在所有地方都使用异常,还是只在特殊场景下使用异常,而在其他情况下仍使用错误码,很明显,从对开发人员友好性方面考虑,始终使用一种机制来报告错误加强了一致性和易用性,故更好。
2、异常增强了API的一致性。这是由于异常的设计目的就是报告错误,相比之下,返回值就有多种用途,报告错误只是其中之一。故使用返回值报告错误可能存在多种模式报告错误,相反,异常则有着相对固定的模式(均是派生自Exception类的对象,均采用try...catch形式捕获)。win32 API就是这种不一致的一个典型的例子,它使用了BOOL、HRESULTS和GetLastError等。
3、错误码机制中,错误处理代码总是和发生错误的代码离得很近,而使用异常处理机制时,开发者有更多的选择余地,既可以在错误发生处捕获处理异常,也可以在调用栈的上游集中处理异常。
4、更容易使错误处理的代码局部化或集中化。在编写稳健的代码时,若用异常报告错误,几乎每一行功能性代码都需要一个if语句,这些if语句存在都目的就是为了处理错误。若改为使用异常,编写代码就容易许多,可以先执行一系列功能性操作,然后将错误处理代码集中放在try块之后,甚至是调用栈的上游。注意:虽说不应使用错误码报告异常,但是还是可以考虑在执行一个成功操作之后返回一些状态信息,比如用来向数据库插入数据的insert方法可以返回插入的记录条数。
5、错误码很容易被忽略且经常被忽略,相反,开发者则无法忽略通过异常机制报告的错误,这样就使得在代码测试期发现更多的缺陷,从而使得发行版更加稳健。
6、异常可以携带丰富的信息用以对错误的原因进行说明。
7、异常允许用户定义未处理异常的处理程序(handler)。理想情形下,一个应用应该能处理所有形式的错误,但这是不现实的,因为开发者不可能预判到所有情况。在使用错误码时,意料之外的错误经常被调用方忽略,程序进行运行并导致未定义的结果。相反,使用异常时,在发生意料之外的异常时,系统会调用未处理异常的handler。该handler既可以将失败记录下来,也可以选择关闭应用程序。与继续让应用运行并产生不确定的结果相比,这种做法显然更可取。
8、异常有助于检测分析(instruction)。异常是经过定义的方法失败模型(method-failure )。正因如此,各种工具(比如调试器,性能分析器、性能计数器等)可能会时刻注意异常的发生。例如,性能监视器(Performance Monitor)会追踪统计异常,而调试器则可以在发生异常时中断。错误码机制就无法享受这些好处。
参考资料:《.NET设计规范》