回答
对
IDisposable
对象明确调用Dispose()
是否合理?
号
是否有其中
using
语句不能正确确保IDisposable
对象清理任何情况下?
当然,还有它是没有意义的使用using
处置对象为您的案件。例如,对象的所需生命周期不受包含using
语句的方法的特定激活约束的所有情况。
考虑例如“接管”另一个一次性物品的一次性物品。 “外部”对象很可能被using
块处置,但是如何处理可能存储在外部对象的专用字段中的“内部”对象,而不需要明确地调用Dispose()
?
一个很好的,干净的答案!我想这个问题从我对C++的退休爱好以及它用于表达RAII的干净语法中冒出来。 – 2012-01-17 00:17:16
@NickStrupat:通过“干净的语法”你的意思是“该字符'}'导致代码执行”。这不是一个“干净”的语法,这是一个危险的误导性语法。划分词法范围的字符不应与*可执行代码*相关联;它在C++中的事实是C++的设计缺陷之一。对我而言,这仍然是一个谜,为什么有人认为这是一个好主意;如果我的资源清理代码很重要,那么我希望它在代码中显式*,以便我可以*读*,*理解*和*调试*它。如果它很重要,不要隐藏它。 – 2012-01-17 00:23:48
@EricLippert - 为了扮演魔鬼的拥护者,在C#中关闭'using'块的'}'可以引起代码执行。你觉得这是“危险的误导”的语法,还是在区块开始时出现的“使用”足以免除它? – kvb 2012-01-17 12:34:17
在某些情况下,根本不可能避免显式调用Dispose
并仍保持适当的语义。例如,考虑具有IDisposable
类型字段的IDisposable
对象。他们必须我们Dispose
显式调用处置场
class Container : IDisposable {
private readonly IDisposable _field;
public void Dipose() {
// Don't want a using here.
_field.Dispose();
}
}
好吧,你仍然可以使用一个使用块来触发处理...但是它会很奇怪,因为它不会匹配对象的整个生命周期,只是它的死亡。 'using'控件表达式不必创建对象,只需分配一个变量即可。 – 2012-01-16 23:06:12
@BenVoigt是你*可以*使用使用。这将是一个有点矫枉过正; 0 – JaredPar 2012-01-16 23:06:58
如果一次性类型的创建实例的成本高(例如它封装了一个远程连接的类型),您可能希望重新使用实例摊销成本。在这种情况下,using
将不会有用,您必须在某个时间呼叫Dispose
。
我会投票反对这样的规则,如果你有一个对象你想多次使用多个函数调用,使用声明将强制处理该对象,下一次你想使用它,你有重新初始化...
一个using
声明(这确实是简写一个try /终于与Dispose
称为finally块)可以在您获取资源,利用它,那么同一个方法内处理它的场景。如果您没有这种资源的线性使用情况(例如,它的使用情况在方法中分开),您必须致电Dispose
。
一个很自然的假设是,你可以随时拨打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
的一揽子规则不适用,即使对象的生命周期包含在一个函数调用中。
- 1. lambdify,避免显式调用
- 2. 是否连续调用errno来避免?
- 3. 是否有理由避免slf4j?
- 4. 是否会自动调用Dispose?
- 5. Form.Dispose()是否在Dispose()中调用控件?
- 6. 是否可以避免在plpgsql函数中显式转换组合类型?
- 7. 是否有任何理由避免Java中的哨兵模式?
- 8. 避免调用DAO.getAll()
- 9. 避免JDBC调用
- 10. 是否可以物理地重组mongoDB集合以避免使用sort()?
- 11. 模式,以避免循环调用
- 12. 我可以避免显式调用RaisePropertyChanged的依赖属性吗?
- 13. 是否有任何理由避免使用bigint代替主键?
- 14. 是否有可能避免在Dart中默认调用superconstructor?
- 15. 避免与策略模式耦合
- 16. 避免嵌套调用
- 17. 避免递归调用.ajax();
- 18. 避免reppetitive respond_to?调用
- 19. 如何避免调用get_query_set()
- 20. 避免需要调用ProcessMessages
- 21. 从事件处理程序的实例调用Dispose是否安全?
- 22. 如何避免显式解码内容?
- 23. 在Haskell中避免显式递归
- 24. 如何避免显式类型签名?
- 25. 是否JNA系统()避免叉
- 26. 如何避免在模式匹配警卫中显式.isDefinedAt()调用
- 27. CA2000:Microsoft.Reliability DisposeObjectsBeforeLosingScope异常,即使最后有显式Dispose()调用
- 28. 使用Ninject2 InRequestScope时,Dispose是否可以进行清理?
- 29. 检测手机是否老化/ NEXUS4以避免显示问题
- 30. 在调用Dispose之前,是否需要关闭SqlDataReader?
尽管我喜欢让垃圾收集器为我管理我的记忆,但如果我有任何理由这样做,对于调用Dispose()我毫无保留。 – 2012-01-16 23:08:24
@SamIam:调用Dispose的要点是释放内存管理器*不为您提供的资源*。 Dispose是明确的关于管理*非内存*资源,所以不要把内存管理器放进去。 – 2012-01-16 23:15:48