要包装一个异常,你应该把它指定为新异常的内部异常然后抛出这个新的异常。这个实践应该只在原始异常不能够为接收者传达足够含意,或者该异常的调用堆栈是令接收者费解的或者是没有兴趣的情形之下才被使用。例如,考虑一个为了管理基于 XML 的配置文件而提供了功能的库。其中,配置文件管理器使用一个 XML 读取器来读取文件。如果某个配置文件拥有错误的格式,那么 XML 读取器就可以抛出一个为 XML 读取器和它所支持的类型而包括了一条消息和调用堆栈细节的异常,并且这个被抛出的异常对于应用程序的用户来说是毫无意义的。因此,在这种情节中就比较适合为配置文件管理器而包装 XML 读取器的异常并且重新抛出一个以真实自然的方式来表述问题的新异常。
下列指导方针有助于确保你在适当的时候正确地对异常进行包装。
考虑把从底层中被抛出的特殊异常包装到一个更加适当的异常中,如果底层异常在高层操作的环境中没有任何意义。
这种情况应该是很少出现的,因为它会让调试变得更加困难。但是在你能够确定底层异常从来都不是真实的错误来源的时候,这样做是合适的。
避免捕获并且包装非特殊的异常。
这个实践应该是被避免的,因为它会对错误进行隐藏。遵循这个规则的异常就有可能包括这样一种情况:包装者异常传达了一个比原始异常的实际类型更加能够吸引调用者的苛刻条件。例如,TypeInitializationException 异常就包装了所有从静态构造器中被抛出的异常。
在包装异常的时候指定内部的异常。
这有助于通过工具来显示问题的底层细节并且能够有助于代码的调试。下列代码范例就示范了一个异常的包装。
C#
public void SendMessages() {try { EstablishConnection();}catch (System.Net.Sockets.SocketException e){throw new CommunicationFailureException("Cannot access remote computer.",e);} }