gpt4 book ai didi

c# - 可能抛出异常时清理多个资源的优雅方式

转载 作者:太空宇宙 更新时间:2023-11-03 19:27:36 24 4
gpt4 key购买 nike

我正在编写一些大量使用异常来处理某些错误情况的代码(当然这不是最好的设计,但我正在使用它)。

当代码中发生异常时,我需要一种优雅的方式来清理所有打开的或临时的资源。

这可以像这样执行:

try
{
foo();
bar();
}
catch (Exception)
{
// Oops, an error occurred - let's clean up resources
// Any attempt to cleanup non-existent resources will throw
// an exception, so let's wrap this in another try block
try
{
cleanupResourceFoo();
cleanupResourceBar();
}
catch
{
// A resource didn't exist - this is non-fatal so let's drop
// this exception
}
}

假设 foo() 方法自行正确清理,但 bar() 方法抛出异常。在清理代码中,我们将调用 cleanupResourceFoo()首先,因为 foo 资源已经被清理,它本身会抛出异常。

这意味着 cleanupResourceBar() 不会被调用,我们将以资源泄漏告终。

当然我们可以像这样重写内部的 try/catch block :

try
{
cleanupResourceFoo();
}
catch
{
}
try
{
cleanupResourceBar();
}
catch
{
}

但现在我们变得很丑陋。

我有 C++ 背景,这是我通常会使用 RAII 的那种东西。关于在 C# 中处理此问题的优雅方式的任何建议?

最佳答案

清理资源应该几乎总是通过 using 语句和 IDisposable 来处理 - 所以你只需:

using (FirstResource r1 = ...)
{
using (SecondResource r2 = ...)
{
...
}
}

如果您想在出现异常时清理资源,这种情况比较少见——而且我不希望 RAII 在 C++ 中特别帮助您。您可以使用委托(delegate)来简化此操作:

TryWithCleanUpOnException(foo, cleanUpResourceFoo);
TryWithCleanUpOnException(bar, cleanUpResourceBar);

...

private static void TryWithCleanUpOnException(Action action,
Action cleanUp)
{
bool success = false;
try
{
action();
success = true;
}
finally
{
if (!success)
{
cleanup();
}
}
}

通过不捕获异常,这允许错误传播而不是被吞噬。这通常是您想要的 - 如果不是您的情况,也许您可​​以更准确地解释您的情况。

您已经说过,您实际上想要忽略一些非致命异常 - 但您通常不应该只捕获 Exception 并继续:捕获特定您在特定情况下期望的异常。显然,您的情况可能非常特殊,但这是在大多数情况下都适用的一般性建议。如果确实需要,您可以重构上面的辅助方法以捕获异常。

关于c# - 可能抛出异常时清理多个资源的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7412153/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com