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

时间:2011-10-10 22:29:28

标签: c# exception try-catch dispose

我在构造函数中实例化了一个一次性对象(在我的例子中是一个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()失败/抛出异常的情况下处置该对象。如果这个方法成功了,我现在还不想处理这个对象,因为稍后会有更多的工作要做。

6 个答案:

答案 0 :(得分:6)

为什么不反转逻辑?

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();
}

答案 1 :(得分:2)

不要试图“处理”你实际上无法做任何事情的例外。

除非您从记录诊断中获得一些明确的用途,或者将其作为一种不同的类型重新投掷,否则只需让它失败&在'finally'子句中释放'disposableObject'!

在涉及异常处理时,很多人都会感到困惑,或者做无意义的蠢事。当它出现在底部时,你应该得到一个痕迹。没有关注'赶上&立即重新投掷'。

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();
}

希望这有帮助!

答案 2 :(得分:2)

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

虽然,实际上,除非您要返回对象或将其移除,否则应使用using块并始终将其丢弃。

答案 3 :(得分:0)

为什么Dispose中没有catch

IDisposable disposableObject = InstantiateDisposable();

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

答案 4 :(得分:0)

如何在这样的实用程序对象中包装?

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标志,但是如果您喜欢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

答案 5 :(得分:-1)

当没有错误时,你有没有理由不处理对象?你应该是的!

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

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