在c#中吃掉异常 om nom nom

15 浏览
0 Comments

在c#中吃掉异常 om nom nom

考虑到吞噬异常始终是不好的做法,而重新抛出异常会丢失调用堆栈,那么重构以下代码的正确方式是什么?

吞噬异常:

try
{
  … 执行有意义的操作
}
catch(SomeException ex)
{
   // 吞噬异常
}

0
0 Comments

在C#中,捕获和处理特定类型的异常是一种良好的实践,不仅仅是捕获System.Exception。一个健壮的程序将强制类型化它知道如何处理的异常。异常不应该用于控制流,但通常会根据异常类型需要执行特定的解开程序。

根据具体的类型,您可以选择重新抛出异常,也可以选择不重新抛出。例如,将ASP解析异常抛出到使用导致异常的代码的错误页面将导致无限循环。

以下是一个示例代码,用于捕获和处理不同类型的异常:

try
{
    // 代码块
}
catch (FileIOException)
{
    // 根据特定的异常类型解开并重新抛出
}
catch (UnauthorizedAccessException)
{
    // 根据特定的异常类型解开并重新抛出
}
catch (SomeOtherException)
{
    // 根据特定的异常类型解开并重新抛出
}
catch (Exception)
{
    // 记录并重新抛出异常...添加自定义消息,捕获调用堆栈等。
    // 抛出原始异常
    throw;
    // 或者,抛出自定义的异常,提供更具体的细节,并将原始异常作为内部异常进行捕获
    throw new MyStronglyTypedException();
}
finally
{
    // 始终进行清理操作
}

在上面的代码中,我们使用了不同的catch块来捕获并处理不同类型的异常。如果捕获到FileIOException、UnauthorizedAccessException或SomeOtherException,我们可以根据具体的异常类型执行解开操作,并选择是否重新抛出异常。如果捕获到的异常不是以上任何一种特定类型的异常,我们可以在catch (Exception)块中记录并重新抛出异常,可以选择抛出原始异常或自定义异常。

总之,在C#中,我们应该根据具体的异常类型来捕获和处理异常,避免将异常用于控制流,并根据需要进行解开操作。

0
0 Comments

在上述代码中,try/catch块用于捕获并处理异常。然而,有些人认为这种做法是多余的,因为如果你要抛出异常,为什么还要捕获它呢?有人认为这种模式在记录异常并重新抛出时非常常见。

根据一些讨论和示例,某些情况下了一些使用try/catch块的情况。例如,在记录错误日志时,可以捕获异常并执行必要的操作,然后重新抛出异常以保留调用堆栈。然而,也有人认为这种模式会让日志变得混乱,因为你无法预知上游将记录什么。

一些人还提到了使用AppDomain.CurrentDomain.UnhandledException事件来处理异常的方法,特别是在允许程序崩溃的情况下。

如果你可以通过检查前提条件来避免使用异常处理,那将是最好的方法。然而,有些情况下无法避免异常的发生。如果你不希望异常被吞噬,但又不想在当前位置处理它,那么最好让异常传播到最高层再处理。

因此,根据讨论和意见,可以得出结论,try/catch块的使用是根据具体情况而定的。在一些特定的情况下,捕获异常并重新抛出可以很有用,特别是在记录错误日志或处理异常传播的场景中。然而,在其他情况下,这种模式可能会使代码变得混乱,并且不容易维护。最终,选择是否使用try/catch块取决于具体需求和代码结构。

0
0 Comments

在C#中吃掉异常的问题和解决方法

很多人认为吃掉/抑制异常是非常邪恶的,尤其是使用catch-all语句。但是,如果合理使用,这种方法是没有问题的。在我看来,最糟糕的情况是程序崩溃,这会导致用户完全丢失数据。每次都会导致这种情况的是一个未处理的异常。因此,不处理异常在统计上比抑制异常可能导致的不稳定性风险更加危险。鉴于此,我们可以合理地做一些事情来防止未处理的异常发生。

许多人似乎忘记了catch-all语句通常可以正确处理任何异常,即使他们不知道异常的详细信息。我的意思是,他们可以保证程序状态保持稳定,并且程序在其设计参数内继续运行。或者甚至可能有副作用,例如用户发现一个按钮无响应,但他们仍然不会丢失任何数据(即优雅的降级比致命的崩溃更好)。例如,有时您希望在成功时返回一个值,如果失败则返回默认值for any reason。代码设计的一部分是知道何时向用户报告错误,以及何时代表他们修复问题,使他们的程序“正常工作”。在这种情况下,一个设计良好的catch-all通常是正确的工具。

异常让我担忧。从根本上讲,异常是一个保证程序崩溃的东西,如果我不处理它。如果我只为我预期的异常添加特定的异常处理,那么我的程序本质上是脆弱的。考虑它有多容易被破坏:

- 如果程序员忘记记录他们可能抛出的异常,我将不知道我需要捕获它,我的代码将具有我不知道的漏洞。

- 如果有人更新一个方法,使其抛出一个新的异常类型,这个新的异常可能会一直传递到调用栈,直到它碰到我的代码。但是我的代码没有构建来处理这个异常。不要告诉我我调用的库永远不会改变。

- 每个你特别处理的异常类型都是另一条需要测试的代码路径。它显着增加了测试的复杂性和/或处理代码可能被忽视的风险。

“抑制是邪恶的”观点的基础是所有异常都代表不稳定性或错误,但在许多情况下,程序员仅使用异常返回一些状态信息。例如,FileNotFound。编写文件I/O代码的程序员已经决定on my behalf,缺少文件是一个致命错误。它可能是这样。由我来捕捉这个异常并决定实际上这是一个常见和完全正常,或者是预期的情况。很多时候,抑制异常是必要的,只是为了阻止其他人的“决定”破坏我的应用程序。简单地忽略错误返回代码并不总是一件坏事,特别是考虑到捕获和抑制被滥用的“状态”异常的努力。

默默吃掉/抑制异常的关键是确保这是正确处理它们的方法(在许多情况下,这并不是正确的方法)。因此,您可能不需要重构您的示例代码-它可能不是坏的juju。

0