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

C# 避免显式调用Dispose()是否合理?,c#,idisposable,C#,Idisposable,制定规则禁止对IDisposable对象显式调用Dispose()合理吗 是否存在使用语句的无法正确确保清理IDisposable对象的情况?在某些情况下,无法避免显式调用Dispose,并且仍然保持正确的语义。例如,考虑 IDISPOSTABLE < /Cord>对象,这些对象的字段类型也有“代码> IDISPOSTABLE ”。他们必须向我们显式调用Dispose以处理该字段 class Container : IDisposable { private readonly IDispos

制定规则禁止对
IDisposable
对象显式调用
Dispose()
合理吗


是否存在使用
语句的
无法正确确保清理
IDisposable
对象的情况?

在某些情况下,无法避免显式调用
Dispose
,并且仍然保持正确的语义。例如,考虑<代码> IDISPOSTABLE < /Cord>对象,这些对象的字段类型也有“代码> IDISPOSTABLE ”。他们必须向我们显式调用
Dispose
以处理该字段

class Container : IDisposable {
  private readonly IDisposable _field;

  public void Dipose() {

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

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

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

制定规则禁止对
IDisposable
对象显式调用
Dispose()
合理吗

没有

是否存在使用
语句的
无法正确确保清理
IDisposable
对象的情况

当然,在某些情况下,使用
use
为您处置对象毫无意义。例如,对象的期望生存期不受包含
using
语句的方法的特定激活的约束的所有情况


例如,考虑一个一次性对象,它“接管”了另一个一次性对象的管理。“外部”对象很可能由
使用
块处理,但是如果不使用
语句显式调用
Dispose()

a
如何处理可能存储在外部对象的私有字段中的“内部”对象(这实际上是在finally块中调用的try/finally with
Dispose
)的缩写)用于获取资源,利用它,然后在同一个方法中处置它的场景。如果资源没有这样的线性使用(例如,它的使用在多个方法中被拆分)您必须调用
Dispose

一个自然的假设是,您始终可以对对象调用
Dispose
,这将清理对象的资源,而不管对象处于何种状态

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

一个例子是

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

var serviceClient = new sandbox.SandboxServiceClient();
serviceClient.HelloWorld(name);
if(serviceClient.State == CommunicationState.Faulted)
{
    serviceClient.Abort();
}
else
{
    serviceClient.Dispose();
}
使用
语法切换到
,将导致代码不安全:

using (var serviceClient = new sandbox.SandboxServiceClient()) 
{
    serviceClient.HelloWorld(name);
}  // Here An exception will be thrown if the channel has faulted

你可以争论(就像我们大家一样)这是WCF的一个有缺陷的设计方面,但编程的现实是,我们有时不得不修改我们的风格以适应我们正在使用的框架。下面是一个示例,其中针对显式
Dispose
的一揽子规则无法应用,即使对象的生命周期包含在一个函数调用中。

好吧,您可以D仍然使用using块来触发处理…但这会很奇怪,因为它不匹配对象的整个生命周期,只匹配对象的死亡。
using
control表达式不必创建对象,它只需指定一个变量。@BenVoigt是的,您可以使用using。不过这有点过分了;0尽管我喜欢e为了让垃圾收集器为我管理内存,我对调用Dispose()毫无保留如果我有任何理由这么做。@ SAMIAM:调用DISTAON的目的是释放内存管理器不为您免费的资源。DeSt回事明确地管理非内存资源,所以不要把内存管理器带到它里面。一个好的、干净的答案!我猜想这个问题从我对C++的退休的爱和它的干净的东西中鼓了出来。用于表示RAII的语法。@NickStrupat:clean syntax的意思是“字符
}
导致代码执行”。这不是“clean”语法,这是一个危险的误导性语法。划定词法范围的字符不应该与可执行代码相关联;C++中的事实是C++的设计缺陷之一。为什么我认为这是一个好主意,它仍然是一个谜;如果我的资源清理代码很重要,那么我希望它是解释性的。EricLippert-为了扮演魔鬼代言人,C#中关闭
using
块的
}
可以说也会导致代码执行。你觉得这是“危险的误导”语法,还是“using”的存在在块的开头是否足以原谅它?@kvb:using(或“foreach”或“lock”)清楚地指出它后面的块具有特殊的语义。@EricLippert,我认为Dispose用于正确性并不罕见。例如,调用
Dipose()
StreamWriter上的
刷新其缓冲区。不调用它(依赖于终结)意味着缓冲区永远不会刷新,因此文件的内容不正确。