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