编辑:两个选项如下所示。安全返回构建的IDisposables的最佳方式是什么?
如果你只是使用 IDisposable提供的功能,恰当地命名为using
子句工作正常。如果你是将和IDisposable
包含在一个对象中,则包含对象本身需要为IDisposable
,并且需要实现适当的模式(密封的IDisposable
类或者messier,但是standard virtual
pattern)。
但是有时候辅助工厂的方法对清洁很有好处。如果您在施工后直接返回IDisposable
,则表示您没有问题,但如果您先构建它,然后修改或执行可能会在返回之前抛出异常的代码,则需要安全地拨打.Dispose()
- 但只有,如果有的话一个错误。
例如,不安全的代码看起来是这样的......
DbCommand CreateCommandUnsafely(string commandText)
{
var newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //what if this throws?
return newCommand;
}
解决方案两个安全变种如下...
DbCommand CreateCommandSafelyA(string commandText)
{
DbCommand newCommand = null;
bool success = false;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
success=true;
return newCommand;
} finally{
if (!success && newCommand != null)
newCommand.Dispose(); //...we'll clean up here.
}
}
DbCommand CreateCommandSafelyB(string commandText)
{
DbCommand newCommand = null;
try {
newCommand = connection.CreateCommand();
newCommand.CommandText = commandText; //if this throws...
return newCommand;
} catch {
if (newCommand != null)
newCommand.Dispose(); //...we'll clean up here.
throw;
}
}
安全的变体,A是仅有一个线长,但似乎是惯用的方法。似乎没有任何真正简洁的解决方案,尽管下面的一些海报给出了一些使用lambda的选项来提取封装的逻辑。
与上述任何安全方法的代码膨胀仍然存在,并且与原先看起来像代码特别严重......
return new MyDisposableThing {
OptionA = "X",
OptionB = B.Blabla,
Values = src.Values.Where(priority => priority > 1.0),
};
上面的代码被安全地写入是相当长的时间和更少的可读因为你不能再安全地使用缩短的setter语法。
这看起来像我在别处看到的代码。你知道为什么这是可取的吗? –
捕捉任意异常(正如其他答案似乎倡导的那样)会在特殊情况下引发各种问题,应尽可能避免。通过将处置置于'finally'语句中,标准模式避免捕捉异常,并且(当对象创建失败时)它模仿标称'using'语句的行为。 –