简体   繁体   English

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

[英]Should we implement IDisposable if one member is IDisposable

I think so.我认同。 But take a look at a built-in class in ASP.NET:但是看看 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 .假设我有一个名为fileHttpPostedFile实例。 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 .因为没有显式调用的Dispose方法, file.InputStream.Dispose()在它被破坏之前不会被调用,我认为这违背了IDisposable初衷。 I think the correct implementation should contain a standard IDisposable implementation.我认为正确的实现应该包含一个标准的IDisposable实现。 So, if one of the members implements IDisposable , the class needs to implement it too.因此,如果其中一个成员实现了IDisposable ,则该类也需要实现它。

What are your opinions?你有什么意见? It seems to be a bit complicated.好像有点复杂。

In general, you should implement IDisposable if you own the resource represented by the property - see this question for a discussion on this subject .通常,如果您拥有由属性表示的资源,则应该实现IDisposable - 请参阅此问题以了解有关此主题的讨论

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.我想说的是,因为 HttpPostedFile 在处理 HTTP 请求期间实例化,它不拥有流,因此不会处理它。 The stream will be disposed when the HTTP request processing finishes.当 HTTP 请求处理完成时,流将被释放。

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.如果您的类创建了一个或多个IDisposable对象并持有对它们的唯一引用,那么您的类几乎肯定应该实现IDisposable并处理它创建的IDisposable对象。 If one or more IDisposable objects will be passed into the constructor of your class, then you need to consider a few scenarios:如果一个或多个IDisposable对象将被传递到您的类的构造函数中,那么您需要考虑几种情况:

  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).您的创建者可能希望在您使用完IDisposable后继续使用它,并且肯定会知道何时不再需要它(您的类的语义会让他知道您已经完成了它)。
  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.您的创建者在您使用完IDisposable后不会想要使用它,并且可能不知道您何时将使用它。
  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.您的类可能会在与上述 (1) 相对应的某些情况下以及在某些情况 (2) 中使用,但您的创建者会提前知道适用哪种情况。
  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.对于场景 #1,您不需要实现IDisposable ,尽管实现一个不做任何处理的IDisposable处理程序并让您的消费者使用它可能不是一个坏主意,以防将来应用另一个场景。

For scenario #2, your object should take ownership of the IDisposable , and should Dispose it when done.对于场景#2,您的对象应该拥有IDisposable所有权,并且应该在完成后Dispose它。 I don't really like having objects take unconditional ownership of IDisposable s;我真的不喜欢让对象无条件地拥有IDisposable I prefer to implement things as in #3.我更喜欢实现#3 中的内容。

There are two ways of handling #3.有两种处理方式#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 .我更喜欢的是让您的对象采用参数( Booleanenum )和IDisposable ,指示它是否应该获得IDisposable所有权。 Your class unconditionally implements IDisposable ;你的类无条件地实现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.另一种方法是拥有两个具有公共基类的子类 - 一个子类实现IDisposable而另一个不实现。 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).我更喜欢前一种模式,因为它允许添加一种方法来将IDisposable替换为一个新的(它可能拥有也可能不拥有)。 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;例如,如果我要实现一个带有Image属性的控件,我会有一个SetImage方法,它带有一个参数来指定控件是否应该拥有传入的图像; that method would Dispose the old image if it owned it, and could then either take ownership of the new image or not.如果它拥有旧图像,该方法将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;
}

Scenario #4 is complicated;场景#4 很复杂; the best way to handle it is probably for your object to implement IDisposable by raising a Disposed event.处理它的最佳方法可能是您的对象通过引发Disposed事件来实现IDisposable 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.如果您是最后一个使用它的人,您的创建者可以使用该事件来Dispose对象,或者调整标志或计数器,以便其他代码知道不应代表您未处理该对象。

It depends.这取决于。

Stream is also implemented by TextStream (possibly on top of StringBuilder ), so no unmanaged resources are required. Stream也由TextStream实现(可能在StringBuilder之上),因此不需要非托管资源。

HttpPostedFile may not use any unmanaged resources at all, so it's safe to postpone deconstruction until the garbage collector sees fit. HttpPostedFile可能根本不使用任何非托管资源,因此在垃圾收集器认为合适之前推迟解构是安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM