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 withDispose
)的缩写)用于获取资源,利用它,然后在同一个方法中处置它的场景。如果资源没有这样的线性使用(例如,它的使用在多个方法中被拆分)您必须调用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上的
刷新其缓冲区。不调用它(依赖于终结)意味着缓冲区永远不会刷新,因此文件的内容不正确。