如何仅在引发异常时处理对象?

发布于 2024-12-09 12:46:30 字数 724 浏览 0 评论 0原文

我在构造函数中实例化了一个一次性对象(在我的例子中是 FileStream),并且需要对其进行一些工作。但是,这可能会引发任意数量的不同异常。现在我什至不想过多地处理这些异常,并希望允许它们传播给调用者。但是,我需要先处理该对象。现在最好的方法是什么?现在我只能想到这样的事情:

IDisposable disposableObject = InstantiateDisposable();
bool error = false;
try
{
    DoWork(disposableObject);
}
catch (ReallyBadException e)
{
    error = true;
    throw new EvenWorseException("some message", e);
}
catch (Exception)
{
    error = true;
    throw;
}
finally
{
    if (error) disposableObject.Dispose();
}

这是正确的还是在某些特殊情况下会跳过 Dispose() ?有更简单的方法吗?如果您出于某种原因需要单独捕获一堆不同的异常,并且总是必须复制和复制,那么它会变得有点麻烦。粘贴 error = true; 位。

编辑: 只是为了澄清:我只需要在 DoWork() 失败/抛出异常的情况下处置该对象。如果此方法成功,我还不想处置该对象,因为稍后将有更多工作要做。

I instantiate a disposable object (in my case a FileStream) in my constructor and need to do some work on it. However, this might throw any number of different exceptions. Now I don't even want to mess with these exceptions too much and want to allow them to propagate up to the caller. However, I need to dispose the object first. Now what's the best way to do that? Right now I can only think of something like that:

IDisposable disposableObject = InstantiateDisposable();
bool error = false;
try
{
    DoWork(disposableObject);
}
catch (ReallyBadException e)
{
    error = true;
    throw new EvenWorseException("some message", e);
}
catch (Exception)
{
    error = true;
    throw;
}
finally
{
    if (error) disposableObject.Dispose();
}

Is that even correct or will the Dispose() be skipped in some special cases? Is there an easier way to do that? It gets a bit cumbersome, if you need to catch a bunch of different exceptions seperately for whatever reason and you always have to copy & paste that error = true; bit.

Edit:
Just to clarify: I only need to dispose the object in case of DoWork() failing / throwing an exception. If this method succeeds, I don't want to dispose the object just yet, as there'll be more work to do with it later on.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

∝单色的世界 2024-12-16 12:46:30

为什么不把逻辑倒过来呢?

IDisposable disposableObject = InstantiateDisposable();
bool error = true;
try
{
    DoWork(disposableObject);
    error = false; // if it gets to this line, no exception was thrown
}
catch (ReallyBadException e)
{        
    throw new EvenWorseException("some message", e);
}    
finally
{
    if (error) disposableObject.Dispose();
}

Why not invert the logic?

IDisposable disposableObject = InstantiateDisposable();
bool error = true;
try
{
    DoWork(disposableObject);
    error = false; // if it gets to this line, no exception was thrown
}
catch (ReallyBadException e)
{        
    throw new EvenWorseException("some message", e);
}    
finally
{
    if (error) disposableObject.Dispose();
}
兰花执着 2024-12-16 12:46:30

不要尝试“处理”您实际上无能为力的异常。

除非您从记录诊断或重新抛出不同类型中获得了一些明显的有用性,否则就让它失败并退出。在“finally”子句中释放“disposableObject”!

当谈到异常处理时,很多人都太困惑了,或者做一些毫无意义的事情。当它从底部出来时,您应该会看到一条痕迹。 'catch & '没有意义。立即重新抛出'。

IDisposable disposableObject = InstantiateDisposable();
bool error = true;
try {
    DoWork(disposableObject);
    error = false; // if it gets to this line, no exception was thrown

} finally {
    if (error) disposableObject.Dispose();
}

希望这有帮助!

Don't try and "handle" exceptions you can't actually do anything about.

Unless you've got some clear usefulness from logging a diagnostic, or re-throwing as a different type, just let it fail & release 'disposableObject' in a 'finally' clause!

Many people get too confused, or do pointless mick-muckery, when it comes to exception handling. You should get a trace when it comes out at the bottom. No point in 'catch & immediately re-throw'.

IDisposable disposableObject = InstantiateDisposable();
bool error = true;
try {
    DoWork(disposableObject);
    error = false; // if it gets to this line, no exception was thrown

} finally {
    if (error) disposableObject.Dispose();
}

Hope this helps!

堇色安年 2024-12-16 12:46:30
IDisposable disposable = InstantiateDisposable();
try
{
    try
    {
        DoWork(disposable);
    }
    catch (Exception)
    {
        disposable.Dispose();
        throw;
    }
}
catch (ReallyBadException ex)
{
    throw new EvenWorseException("some message", ex);
}

不过,实际上,除非您要返回对象或将其存储起来以用于某些目的,否则您应该使用 using 块并始终将其丢弃。

IDisposable disposable = InstantiateDisposable();
try
{
    try
    {
        DoWork(disposable);
    }
    catch (Exception)
    {
        disposable.Dispose();
        throw;
    }
}
catch (ReallyBadException ex)
{
    throw new EvenWorseException("some message", ex);
}

Although, really, unless you are returning the object or squirreling it away for something, you should use a using block and always dispose it.

好久不见√ 2024-12-16 12:46:30

为什么不在 catch 中进行 Dispose 呢?

IDisposable disposableObject = InstantiateDisposable();

try
{
    DoWork(disposableObject);
}
catch (ReallyBadException e)
{
    disposableObject.Dispose();
    throw new EvenWorseException("some message", e);
}
catch (Exception)
{
    disposableObject.Dispose();
    throw;
}

Why not Dispose in the catch?

IDisposable disposableObject = InstantiateDisposable();

try
{
    DoWork(disposableObject);
}
catch (ReallyBadException e)
{
    disposableObject.Dispose();
    throw new EvenWorseException("some message", e);
}
catch (Exception)
{
    disposableObject.Dispose();
    throw;
}
薆情海 2024-12-16 12:46:30

包装在这样的实用程序对象中怎么样?

class Disposer : IDisposable
{
    private IDisposable target;

    public Disposer(IDisposable target)
    {
        this.target = target;
    }

    public void Cancel()
    {
        this.target = null;
    }

    public void Dispose()
    {
        this.target?.Dispose();
        Cancel();
    }
}

这相当于管理 bool error 标志,但如果您喜欢使用,则可以说更清晰一些:

IDisposable disposableObject = InstantiateDisposable();
using (Disposer disposer = new Disposer(disposableObject))
{
    try
    {
        DoWork(disposableObject);
        disposer.Cancel();
    }
    catch (ReallyBadException e)
    {
        throw new EvenWorseException("some message", e);
    }
}

// ... continue with disposableObject

How about wrapping within a utility object like this?

class Disposer : IDisposable
{
    private IDisposable target;

    public Disposer(IDisposable target)
    {
        this.target = target;
    }

    public void Cancel()
    {
        this.target = null;
    }

    public void Dispose()
    {
        this.target?.Dispose();
        Cancel();
    }
}

This is equivalent to managing bool error flag, but arguably a bit cleaner if you like using:

IDisposable disposableObject = InstantiateDisposable();
using (Disposer disposer = new Disposer(disposableObject))
{
    try
    {
        DoWork(disposableObject);
        disposer.Cancel();
    }
    catch (ReallyBadException e)
    {
        throw new EvenWorseException("some message", e);
    }
}

// ... continue with disposableObject
淡淡绿茶香 2024-12-16 12:46:30

在没有错误的情况下,您是否有理由不处理该对象?你可能应该是!

使用标准的 using 模式意味着您的对象将始终被安全地处置,然后您只需要担心捕获任何异常 - 例如,ReallyBadException - 需要特别注意。任何其他异常都会向调用者冒泡。

using (IDisposable disposableObject = InstantiateDisposable())
{
    try
    {
        DoWork(disposableObject);
    }
    catch (ReallyBadException e)
    {
        throw new EvenWorseException("some message", e);
    }
}

Is there a reason why you're not disposing the object when there's no error? You probably should be!

Using the standard using pattern means that your object will always be safely disposed, and then you only need to worry about catching any exceptions -- eg, ReallyBadException -- which need special attention. Any other exceptions will bubble up to the caller.

using (IDisposable disposableObject = InstantiateDisposable())
{
    try
    {
        DoWork(disposableObject);
    }
    catch (ReallyBadException e)
    {
        throw new EvenWorseException("some message", e);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文