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

发布于 2024-12-27 03:35:59 字数 152 浏览 1 评论 0原文

制定禁止在 IDisposable 对象上显式调用 Dispose() 的规则是否合理?

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

Is it reasonable to make a rule against explicitly calling Dispose() on an IDisposable object?

Are there any cases where a using statement cannot properly ensure an IDisposable object is cleaned up?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蓬勃野心 2025-01-03 03:35:59

制定禁止在 IDisposable 对象上显式调用 Dispose() 的规则是否合理?

不。

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

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

例如,考虑一个一次性对象“接管”另一个一次性对象的管理。 “外部”对象很可能由 using 块进行处理,但是“内部”对象(可能存储在外部对象的私有字段中)如何在不显式调用 <代码>Dispose()?

Is it reasonable to make a rule against explicitly calling Dispose() on an IDisposable object?

No.

Are there any cases where a using statement cannot properly ensure an IDisposable object is cleaned up?

There are certainly cases where it makes no sense to use using to dispose an object for you. For example, all cases where the desired lifetime of the object is not bound by a particular activation of a method containing a using statement.

Consider for example a disposable object which "takes over management" of another disposable object. The "outer" object may well be disposed by a using block, but how is the "inner" object, likely stored in a private field of the outer object, to be disposed without an explicit call to Dispose()?

韵柒 2025-01-03 03:35:59

在某些情况下,根本不可能避免显式调用 Dispose 并仍然保持正确的语义。例如,考虑具有同样为 IDisposable 类型的字段的 IDisposable 对象。他们必须使用显式调用 Dispose 来处置该字段

class Container : IDisposable {
  private readonly IDisposable _field;

  public void Dipose() {

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

In some cases it's simply not possible to avoid an explicit call to Dispose and still maintain proper semantics. For example consider IDisposable objects which have a field also of type IDisposable. They must us an explicit call to Dispose to dispose the field

class Container : IDisposable {
  private readonly IDisposable _field;

  public void Dipose() {

    // Don't want a using here.
    _field.Dispose();
  }
}
も星光 2025-01-03 03:35:59

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

One natural assumption is that you can always call Dispose on an object, and this will clean up the object's resources, regardless of what state the object is in.

This natural assumption is not always a correct assumption.

An example is with WCF client proxies..

The correct way to manage proxy lifetime is as follows:

var serviceClient = new sandbox.SandboxServiceClient();
serviceClient.HelloWorld(name);
if(serviceClient.State == CommunicationState.Faulted)
{
    serviceClient.Abort();
}
else
{
    serviceClient.Dispose();
}

Switching to the using syntax will result in unsafe code:

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

You could argue (as we all do) that this is a flawed design aspect of WCF, but the reality of programming is that we sometimes have to modify our style to accommodate the frameworks we're using. Here's an example where a blanket rule against explicit Dispose cannot apply, even when the lifetime of the object is contained within one function call.

愛上了 2025-01-03 03:35:59

using 语句(实际上是在 finally 块中调用 Dispose 的 try/finally 的简写)适用于获取资源、使用它,然后用一种相同的方法处理它。如果您没有这样的资源线性使用(例如,它的使用被分散在不同的方法中),您将必须调用Dispose

A using statement (which really is shorthand for a try/finally with Dispose called in the finally block) is for scenarios where you acquire a resource, make use of it, then dispose of it within one same method. If you don't have such a linear usage of the resource (e.g. its usage is split across methods) you will have to call Dispose.

海夕 2025-01-03 03:35:59

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

If the cost of creating instances of a disposable type is high (e.g. a type which encapsulates a remote connection), you may want to reuse instances to amortize the cost. In that case using will not be useful and you'll have to call Dispose at some point.

魂牵梦绕锁你心扉 2025-01-03 03:35:59

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

I would vote against such rule, what if you have an object you want to use multiple times across several function calls, a using statement will force the disposal of that object, the next time you want to use it, you have to re-initialize...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文