我在构造函数中实例化一个一次性对象(在我的例子中是一个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()
失败/抛出异常的情况下处置该对象。如果这个方法成功,我不想暂时处理这个对象,因为稍后会有更多的工作要做。
为什么不颠倒逻辑呢?
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();
}
不要试图“处理”你实际上无法做任何事情的例外。
除非您通过记录诊断或重新投掷作为一种不同的类型获得了一些明确的用处,否则只需让它失败并在'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();
}
希望这可以帮助!
IDisposable disposable = InstantiateDisposable();
try
{
try
{
DoWork(disposable);
}
catch (Exception)
{
disposable.Dispose();
throw;
}
}
catch (ReallyBadException ex)
{
throw new EvenWorseException("some message", ex);
}
虽然,实际上,除非你要返回物体或将物品扔掉,否则你应该使用using
块并且总是将它丢弃。
为什么不在Dispose
中的catch
?
IDisposable disposableObject = InstantiateDisposable();
try
{
DoWork(disposableObject);
}
catch (ReallyBadException e)
{
disposableObject.Dispose();
throw new EvenWorseException("some message", e);
}
catch (Exception)
{
disposableObject.Dispose();
throw;
}
如何在这样的实用程序对象中包装?
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
当没有错误时,你有没有理由不处理对象?你可能应该!
使用标准的using
模式意味着您的对象将始终被安全地处理,然后您只需要担心捕获任何异常 - 例如,ReallyBadException
- 需要特别注意。任何其他异常都会冒泡到调用者。
using (IDisposable disposableObject = InstantiateDisposable())
{
try
{
DoWork(disposableObject);
}
catch (ReallyBadException e)
{
throw new EvenWorseException("some message", e);
}
}