避免显式调用Dispose()是否合理?

时间:2012-01-16 23:02:41

标签: c# idisposable

制定规则以明确调用Dispose()对象上的IDisposable是否合理?

是否存在using语句无法正确确保清除IDisposable对象的情况?

6 个答案:

答案 0 :(得分:11)

  

制定规则以明确调用Dispose()对象上的IDisposable是否合理?

没有

  

是否存在using语句无法正确确保清除IDisposable对象的情况?

在某些情况下,使用using为您处理对象毫无意义。例如,对象的所需生命周期不受包含using语句的方法的特定激活的约束。

考虑一个一次性物品,它接管管理"另一个一次性物品。 "外部"对象很可能被using块处理掉,但是"内部"是什么?对象,可能存储在外部对象的私有字段中,在没有显式调用Dispose()的情况下进行处置?

答案 1 :(得分:5)

在某些情况下,根本无法避免对Dispose的显式调用并仍然保持正确的语义。例如,考虑具有IDisposable类型字段的IDisposable个对象。他们必须明确要求Dispose处理该字段

class Container : IDisposable {
  private readonly IDisposable _field;

  public void Dipose() {

    // Don't want a using here.
    _field.Dispose();
  }
}

答案 2 :(得分:3)

一个自然的假设是你总是可以在一个对象上调用Dispose,这将清理对象的资源,无论对象处于什么状态。

这种自然假设并不总是正确的假设。

一个例子是WCF client proxies.

管理代理生存期的正确方法如下:

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的一揽子规则无法应用,即使对象的生命周期包含在一个函数调用中也是如此。

答案 3 :(得分:2)

using语句(它实际上是在finally块中调用Dispose的try / finally的简写)用于获取资源,使用它,然后处理它的场景在一个相同的方法。如果您没有对资源进行这种线性使用(例如,它的使用是按方法划分的),则必须调用Dispose

答案 4 :(得分:1)

如果创建一次性类型实例的成本很高(例如,封装远程连接的类型),您可能希望重用实例来分摊成本。在这种情况下,using将无用,您必须在某个时候致电Dispose

答案 5 :(得分:1)

我会投票反对这样的规则,如果你想在多个函数调用中多次使用一个对象,一个using语句将强制处理该对象,下次你想要使用它时,你必须重新初始化...