避免显式调用Dispose()合理吗
本文关键字:Dispose 调用 | 更新日期: 2023-09-27 18:20:41
制定一条规则来反对在IDisposable
对象上显式调用Dispose()
合理吗?
是否存在using
语句无法正确确保IDisposable
对象被清理的情况?
制定一条规则禁止在
IDisposable
对象上显式调用Dispose()
是否合理?
没有。
是否存在
using
语句无法正确确保IDisposable
对象被清理的情况?
当然,在某些情况下,使用using
为您处理对象是没有意义的。例如,对象的期望寿命不受包含using
语句的方法的特定激活的约束的所有情况。
例如,考虑一个"接管"另一个一次性对象的一次性对象。"外部"对象很可能由using
块处理,但是,如果不显式调用Dispose()
,如何处理可能存储在外部对象的私有字段中的"内部"对象?
在某些情况下,根本无法避免对Dispose
的显式调用并保持正确的语义。例如,考虑具有同样类型为IDisposable
的字段的IDisposable
对象。他们必须明确调用Dispose
来处理字段
class Container : IDisposable {
private readonly IDisposable _field;
public void Dipose() {
// Don't want a using here.
_field.Dispose();
}
}
一个自然的假设是,您总是可以在对象上调用Dispose
,这将清理对象的资源,而不管对象处于什么状态。
这种自然的假设并不总是正确的。
WCF客户端代理就是一个例子。。
管理代理生存期的正确方法如下:
var serviceClient = new sandbox.SandboxServiceClient();
serviceClient.HelloWorld(name);
if(serviceClient.State == CommunicationState.Faulted)
{
serviceClient.Abort();
}
else
{
serviceClient.Dispose();
}
切换到using
语法将导致不安全的代码:
using (var serviceClient = new sandbox.SandboxServiceClient())
{
serviceClient.HelloWorld(name);
} // Here An exception will be thrown if the channel has faulted
你可能会争辩说(就像我们大家所做的一样)这是WCF的一个有缺陷的设计方面,但编程的现实是,我们有时不得不修改我们的风格来适应我们正在使用的框架。这里有一个例子,即使对象的生存期包含在一个函数调用中,也不能应用针对显式Dispose
的一揽子规则。
using
语句(实际上是try/finaly的简写,在finally块中调用Dispose
)适用于获取资源、使用资源,然后在同一方法中处理资源的场景。如果您对资源没有这样的线性使用(例如,它的使用在方法之间划分),您将不得不调用Dispose
。
如果创建一次性类型的实例的成本很高(例如,封装远程连接的类型),则可能需要重用实例来分摊成本。在这种情况下,using
将不起作用,您将不得不在某个时候调用Dispose
。
我会投票反对这样的规则,如果你有一个对象要在几个函数调用中多次使用,using语句会强制处理该对象,下次你想使用它时,你必须重新初始化。。。