禁止显式调用 Dispose()
方法是否合理?
using
语句有无法确保正确清理 IDisposable
对象的情况吗?
禁止显式调用 Dispose()
方法是否合理?
using
语句有无法确保正确清理 IDisposable
对象的情况吗?
是否有道理制定一个规则禁止显式调用
Dispose()
来释放IDisposable
对象?
不是。
是否存在某些情况,使用
using
语句无法正确确保清除IDisposable
对象?
当需要清除对象的期望寿命不受包含using
语句的方法的特定激活限制时,有一些情况确实不适合使用using
自动清除对象。例如,对于"接管管理"另一个可释放对象的可释放对象,可能需要在外部对象被using
块释放之前通过显式调用Dispose()
清除内部对象,而该内部对象通常存储在外部对象的私有字段中。
}
会导致代码执行”。这不是一种“清晰”的语法,而是一种极具误导性的语法。用于标记词法作用域的字符不应与可执行代码相关联;在C++中,它是C++设计缺陷之一。我仍然感到困惑的是,为什么有人认为这是一个好主意;如果我的资源清理代码很重要,那么我希望它在代码中是明确的,这样我就可以阅读、理解和调试它。如果它很重要,就不要隐藏它。 - Eric Lippertusing
块的}
也可能导致代码执行。您认为这是“危险误导”的语法,还是块开头的“using”足以原谅它? - kvbDipose()
会刷新其缓冲区。如果不调用它(并依赖于终结),则缓冲区永远不会被刷新,因此文件的内容是不正确的。 - svick在某些情况下,无法避免显式调用Dispose
并仍然保持正确的语义。例如,考虑具有类型为IDisposable
的字段的IDisposable
对象。它们必须使用显式调用Dispose
来释放该字段。
class Container : IDisposable {
private readonly IDisposable _field;
public void Dipose() {
// Don't want a using here.
_field.Dispose();
}
}
using
控制表达式不必创建对象,只需分配一个变量即可。 - Ben Voigt人们通常会认为,无论对象处于什么状态,都可以随时调用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
语句(实际上是一个带有Dispose
在finally块中调用的try/finally的简写)适用于获取资源、使用它,然后在同一方法内处理该资源的情况。如果您没有这样线性使用资源(例如,其使用分散在多个方法中),则必须调用Dispose
。
using
将无法发挥作用,您必须在某个时候调用 Dispose
。