c#和捕获异常

c#和捕获异常,c#,exception,C#,Exception,在处理异常时附加常规异常捕获是否是一种良好的做法。举个例子可以让这个问题更清楚 try{ // do something }catch(spomespecificException1 ex){ //logging and other stuff }catch(spomespecificException2 ex){ //logging and other stuff }catch(Exception ex){ //logging and other stuff } 我是否应该将异常捕获

在处理异常时附加常规异常捕获是否是一种良好的做法。举个例子可以让这个问题更清楚

try{
 // do something
}catch(spomespecificException1 ex){
 //logging and other stuff
}catch(spomespecificException2 ex){
 //logging and other stuff
}catch(Exception ex){
 //logging and other stuff
}

我是否应该将异常捕获附加到堆栈中

,这取决于情况以及在捕获异常之前希望让异常冒泡到堆栈上多远

肯定有赞成和反对的理由,但如果没有针对你具体情况的细节,就不可能说出来


那么,有没有一个通用的“规则”?不。

一般来说,您根本不应该捕获这些异常。不要捕捉您实际上不知道如何处理的异常


“Handle”的意思是修复。如果您无法解决问题,或者无法添加其他信息,则不要捕获异常。

如果您希望执行与该异常相关的特定处理,则您发布的代码是可以的—您希望在其他捕获块中执行该处理。一个很好的例子可能是当您尝试连接到SQL数据库时,您可以用不同的方式处理不同的错误消息


另外,请记住,您可以在末尾添加一个“finally”块来执行所有清理(和公共)处理代码,但是您不会在其中获得异常信息。异常通常会发生,特别是在您访问应用程序之外的内容(如连接错误等)时

如果您想过滤出异常类型,并为每个特定类型做一些不同的操作,那么这样做没有什么错


更好的编码实践是首先防止这些异常的发生。

我认为(并且经常这样做)一般规则是,除非您知道如何处理异常,否则不要捕获异常,因此,一般来说,不要捕捉异常。@John Saunders捕捉异常如何,这样您就可以抛出自己的自定义exceptions@RichardBanks:当然可以,但几乎不需要自定义异常。仅当调用方将显式捕获您的异常时才使用它们。如果调用方代码对
MyCustomException
的反应与对
invalidooperationexception
的反应相同,则不需要
MyCustomException
。如果您只是想自定义
消息
,那么
字符串.格式
就可以了。@John Saunders创建自定义异常并不意味着代码更少。如果一个方法必须处理5个异常,那么为什么不将抛出的异常包装成一个自定义异常,那么调用方只需捕获一个自定义异常。@RichardBanks:那么为什么要费心捕获所有不同的异常类型,只是捕捉异常?这实际上取决于情况的上下文,可能也是相当主观的。如果没有更多细节,我不认为你真的能说“是”或“否”。相关线程-我的一般经验法则是在某个点捕获一般异常,该点将中止一个工作单元,但让该过程继续。也就是说,如果我有一个订单处理服务,并且我正在下订单,我希望捕获下订单时出现的任何异常,这样我就不会关闭该服务,但是不应该捕获和使用比该服务更深的任何内容。在我看来,这与约翰的Handle/Fix定义是一致的。但那是我…@JamesMichaelHare:你怎么知道停止服务可能不是正确的事情?也许服务被破坏得太厉害了,当它不抛出异常时,就破坏了订单。关闭服务(并通知您以便尽快修复)可能正是正确的做法。@John:这始终是一个选项。但如果同时取消其他正在进行的订单,也可能导致可怕的财务后果。我们向监控工具报告所有异常以及所有性能计数器,以便从仪表板上查看应用程序的状态,包括抛出的异常。事实并非如此。在许多情况下,您希望捕获异常以正常退出,请通知用户或管理员。很少你只想让异常不被处理。为了记录而捕获怎么样?@Tom:但是如果是这样的话,你正在处理它,否则你会捕获并重新捕获。我认为主要的一点是永远不要使用无法修复的异常(修复意味着正确处理并继续)。如果您必须捕获异常以记录它,那么应该尽可能接近调用堆栈的顶部。而且,在许多情况下,框架将为您记录日志。例如,ASP.NET就是这样。并确保您的日志记录会触发服务器监控工具,如SCOM或Big Brother。