如果一个成员是 IDisposable,我们是否应该实现 IDisposable?

发布于 2024-12-05 01:32:43 字数 507 浏览 1 评论 0原文

我想是的。但看一下 ASP.NET 中的内置类:

public sealed class HttpPostedFile
{
    public Stream InputStream { get; }   // Stream implements IDisposable
    // other properties and methods
}

假设我有一个名为 fileHttpPostedFile 实例。由于没有显式调用的 Dispose 方法,所以在析构之前不会调用 file.InputStream.Dispose() ,我认为这违背了 file.InputStream.Dispose() 的初衷代码> IDisposable 。我认为正确的实现应该包含标准的 IDisposable 实现。因此,如果其中一个成员实现了 IDisposable,则该类也需要实现它。

你有什么意见?好像有点复杂。

I think so. But take a look at a built-in class in ASP.NET:

public sealed class HttpPostedFile
{
    public Stream InputStream { get; }   // Stream implements IDisposable
    // other properties and methods
}

Suppose I have an instance of HttpPostedFile called file. Since there is no Dispose method to explicitly invoke, file.InputStream.Dispose() won't be invoked until it's destructed, which I think goes against the original intention of IDisposable. I think the correct implementation should contain a standard IDisposable implementation. So, if one of the members implements IDisposable, the class needs to implement it too.

What are your opinions? It seems to be a bit complicated.

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

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

发布评论

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

评论(3

深居我梦 2024-12-12 01:32:43

一般来说,如果您拥有属性所代表的资源,则应该实现IDisposable - 请参阅此问题用于讨论该主题

我想说,因为 HttpPostedFile 是在处理 HTTP 请求期间实例化的,所以它不拥有该流,因此不会处置它。当 HTTP 请求处理完成时,该流将被释放。

In general, you should implement IDisposable if you own the resource represented by the property - see this question for a discussion on this subject.

I'd say that because HttpPostedFile is instantiated during processing of an HTTP request, it doesn't own the stream, and hence doesn't dispose it. The stream will be disposed when the HTTP request processing finishes.

西瑶 2024-12-12 01:32:43

如果您的类创建一个或多个 IDisposable 对象并保存对它们的唯一引用,那么您的类几乎肯定应该实现 IDisposable 并处置 IDisposable它创建的对象。如果一个或多个 IDisposable 对象将被传递到类的构造函数中,那么您需要考虑以下几种情况:

  1. 您的创建者可能希望在您创建之后继续使用 IDisposable已经完成了,并且肯定会知道何时不再需要它(您的类的语义会让他知道您已经完成了)。
  2. 在您使用完 IDisposable 后,您的创建者将不想再使用它,并且可能不知道您什么时候会用完它。
  3. 您的类可能会在与上述 (1) 相对应的某些情况下使用,在某些情况下 (2) 可能会使用,但您的创建者会提前知道适用哪种情况。
  4. 您的创建者无法预测在您使用完该对象后他是否想要继续使用该对象。

对于场景 #1,您无需实现 IDisposable,尽管实现一个不执行任何操作的 IDisposable 处理程序并让您的消费者使用它可能不是一个坏主意,以防将来出现另一种情况。

对于场景#2,您的对象应该拥有 IDisposable 的所有权,并在完成后Dispose 它。我真的不喜欢让对象无条件拥有 IDisposable 的所有权;我更喜欢按照#3 中的方式实现。

有两种处理#3 的方法。我更喜欢的是让您的对象采用一个参数(Booleanenum)以及 IDisposable,指示它是否是应该取得 IDisposable 的所有权。你的类无条件实现IDisposable;该实现会处理它已拥有所有权的任何对象,但不会处理尚未拥有的对象。另一种方法是让两个子类具有共同的基类 - 一个子类实现 IDisposable,而另一个则不实现。我更喜欢前一种模式,因为它允许添加一种方法来用新的(它可能会也可能不会拥有所有权)替换 IDisposable 。例如,如果我要实现具有 Image 属性的控件,我将有一个 SetImage 方法,该方法带有一个参数来指定该控件是否应拥有传入的图像;该方法将Dispose旧图像(如果它拥有它),然后可以获取或不获取新图像的所有权。

bool OwnMyImage;
Image MyImage;
void SetImage(Image NewImage, bool TakeOwnership)
{
    IDisposable oldDisposable; // Could reuse one variable for multiple IDisposables
    if (OwnMyImage)
    {
        oldDisposable = Threading.Interlocked.Exchange(MyImage, null);
        if (oldDisposable != null)
        {
            oldDisposable.Dispose();
        }
    }
    OwmMyImage = TakeOwnership;
    MyImage = NewImage;
}

场景 #4 很复杂;处理它的最佳方法可能是让您的对象通过引发 Dispose 事件来实现 IDisposable。您的创建者可以使用该事件来Dispose该对象(如果您是最后一个使用该对象的人),或者调整标志或计数器,以便其他代码知道该对象不应留在您的设备上。代表。

If your class creates one or more IDisposable objects and holds the only references to them, then your class should almost certainly implement IDisposable and dispose the IDisposable objects it created. If one or more IDisposable objects will be passed into the constructor of your class, then you need to consider a few scenarios:

  1. Your creator may want to keep using the IDisposable after you're done with it, and will certainly know when it's no longer needed (the semantics of your class would let him know you're done with it).
  2. Your creator won't want to use the IDisposable after you're done with it, and may not know when you're going to be done with it.
  3. Your class may be used in some circumstances corresponding to (1) above, and in some circumstances (2), but your creator will know in advance which circumstance applies.
  4. Your creator can't predict whether he's going to want to keep using the object after you're done with it.

For scenario #1, there's no need for you to implement IDisposable, though it might not be a bad idea to implement a do-nothing IDisposable handler and have your consumers use it, in case another scenario applies in future.

For scenario #2, your object should take ownership of the IDisposable, and should Dispose it when done. I don't really like having objects take unconditional ownership of IDisposables; I prefer to implement things as in #3.

There are two ways of handling #3. The one I prefer is for your object to take a parameter (either a Boolean or an enum) along with the IDisposable, indicating whether it is supposed to take ownership of the IDisposable. Your class unconditionally implements IDisposable; the implementation disposes of any objects it has taken ownership of, but not those it hasn't. An alternative is to have two subclasses with a common base class - one subclass implements IDisposable and the other does not. I prefer the former pattern, because it allows for the addition of a method to replace an IDisposable with a new one (of which it may or may not take ownership). For example, if I were implementing a control with an Image property, I would have a SetImage method which with a parameter to specify whether the control should own the passed-in image; that method would Dispose the old image if it owned it, and could then either take ownership of the new image or not.

bool OwnMyImage;
Image MyImage;
void SetImage(Image NewImage, bool TakeOwnership)
{
    IDisposable oldDisposable; // Could reuse one variable for multiple IDisposables
    if (OwnMyImage)
    {
        oldDisposable = Threading.Interlocked.Exchange(MyImage, null);
        if (oldDisposable != null)
        {
            oldDisposable.Dispose();
        }
    }
    OwmMyImage = TakeOwnership;
    MyImage = NewImage;
}

Scenario #4 is complicated; the best way to handle it is probably for your object to implement IDisposable by raising a Disposed event. Your creator can use that event to do either Dispose the object if you were the last one using it, or adjust a flag or counter so that other code will know the object shouldn't be left undisposed on your behalf.

菩提树下叶撕阳。 2024-12-12 01:32:43

这取决于。

Stream 也由 TextStream 实现(可能在 StringBuilder 之上),因此不需要非托管资源。

HttpPostedFile 可能根本不使用任何非托管资源,因此可以安全地推迟解构,直到垃圾收集器认为合适。

It depends.

Stream is also implemented by TextStream (possibly on top of StringBuilder), so no unmanaged resources are required.

HttpPostedFile may not use any unmanaged resources at all, so it's safe to postpone deconstruction until the garbage collector sees fit.

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