C# 什么是;“仅捕获您可以处理的异常”;真的吗?
我的任务是为我正在从事的.NET/C项目编写一份异常处理策略和指导方针文档。我很难做到这一点。关于如何/何时抛出、捕获、包装异常,有大量可用的信息,但我希望描述除了包装和抛出异常之外,在catch块中应该进行哪些操作C# 什么是;“仅捕获您可以处理的异常”;真的吗?,c#,exception-handling,C#,Exception Handling,我的任务是为我正在从事的.NET/C项目编写一份异常处理策略和指导方针文档。我很难做到这一点。关于如何/何时抛出、捕获、包装异常,有大量可用的信息,但我希望描述除了包装和抛出异常之外,在catch块中应该进行哪些操作 try { DoSomethingNotNice(); } catch (ExceptionICanHandle ex) { //Looking for examples of what people are doing in catch blocks //oth
try
{
DoSomethingNotNice();
}
catch (ExceptionICanHandle ex)
{
//Looking for examples of what people are doing in catch blocks
//other than throw or wrapping the exception, and throwing.
}
提前谢谢这正是我的意思。如果您希望正在运行的代码抛出异常,并且当抛出异常时,您的代码知道发生了什么错误以及如何继续,那么捕获异常并处理它 基本上,规则的存在是为了防止反模式,例如:
try
{
...
}
catch(Exception ex)
{
throw;
}
这里的catch只不过是在释放调用堆栈时增加了一个减速。如果你真的不想做任何事情,除了你捕获的例外,你甚至不应该为捕获而烦恼
一个相关但更有效的情况是,您不关心抛出的异常,但在所有情况下都需要清理。在这种情况下,跳过捕捉;你不需要它,只要试一下就行了
编辑:要回答帖子中的问题,而不仅仅是主题,您可以编写如下规则:“不要编写不起任何作用的try-catch语句,或者只重新调用捕获的异常。所有catch语句都应该执行与抛出的异常相关的增值操作。”
例如,假设您正试图使用用户登录应用程序时提供的凭据连接到SQL Server实例。很多事情都可能出错,有些是你无法预料的,有些是你应该做的
- 服务器没有响应-您可以重试;可能在catch中递归调用连接方法,使用“重试计数器”来中断本来无限的循环
- 用户身份验证失败-在对话框上以红色显示友好(或不太友好,但简洁易懂)消息
- 用户无权连接到指定的数据库-取决于您的安全设置;在大多数办公室中,您应该向DBA发送电子邮件,因为这意味着他创建了登录名,但忘记了分配适当的权限
- 网络不可用:您可以通过登录对话框或新对话框上的错误警告用户,重试几次,等等
- 被零除-WTF?在登录过程中,什么可能导致Div为零?您不希望出现这种异常,您不知道在这种情况下发生了什么错误,因此无法继续运行代码,所以不要捕获它
- 如果出现任何问题,出于审计/安全目的,您可能希望将消息记录到文件或共享资源中。如果您想继续执行,这应该发生在较低的级别上,如果您想在之后优雅地关闭,则应该发生在较高的级别上
如果您的代码能够优雅地处理特定类型的异常,请捕获并处理它,然后让代码继续运行。如果没有,让异常向上传播,因为它可能是在更高级别捕获的,或者可能是您不应该捕获的真正错误,因为它可能会掩盖错误。您不应该捕获无法处理的异常,但您可以捕获您可能能够处理的异常:
try
{
DoSomethingNotNice();
}
catch (ExceptionIMightBeAbleToHandle ex)
{
if(iCanHandle(ex))
thenHandle(ex);
else
throw;
}
请注意,单独使用throw
应该保留堆栈跟踪信息
如果您在捕获异常时可以执行某种操作,则可以优雅地处理
FileNotFoundException
(例如,执行一段代码,该代码将执行try语句中尝试的功能,但执行方式不同,但效率可能较低,或者只是通知用户无法执行其操作),然后您应该捕获它并执行此操作。如果您只是记录异常以便稍后跟踪问题,那么您应该重新显示异常throw;
(而不是throw ex;
),以防有其他代码块可以处理该类型的异常
try
{
DoSomethingNotNice();
}
catch (ExceptionICanHandle ex)
{
//Looking for examples of what people are doing in catch blocks
//other than throw or wrapping the exception, and throwing.
}
捕获异常以将捕获的异常包装到您自己的异常中也是可以接受的,这可能对调用函数更有意义。一些示例:
这一切都取决于出了什么问题。关键是,仅仅抓住并重新投掷对任何人都没有用处。我认为这条常见建议的基本思想是避免出现以下情况:
try
{
SomeImportantResource = GetSomeImportantResource();
SomeOtherImportantResource = GetSomeOtherImportantResource();
}
catch (Exception ex)
{
SomeGlobalErrorHandlingMechanism(ex);
}
我一直在工作