Should we implement IDisposable if one member is IDisposable

I think so. But look at the 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 call, file.InputStream.Dispose() will not be called until it is destroyed, which, in my opinion, contradicts the original purpose of IDisposable . I think that the correct implementation should contain the standard implementation of IDisposable . Therefore, if one of the participants implements IDisposable , the class must also implement it. What do you think? It seems a bit complicated.

+4
source share
3 answers

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

I would say that since the HttpPostedFile is created when processing an HTTP request, it does not own the stream and therefore does not manage it. The stream will be deleted after processing the HTTP request.

+7
source

It depends.

The stream is also implemented by TextStream (possibly on top of StringBuilder), so unmanaged resources are not required. Perhaps the HttpPostedFile does not use any unmanaged resources at all, so it is safe to defer deconstruction until the garbage collector is needed.

0
source

If your class creates one or more IDisposable objects and contains only references to them, then your class should almost certainly implement IDisposable and delete the IDisposable objects that it created. If one or more IDisposable objects are passed to the constructor of your class, you need to consider several scenarios:

  • Your creator may want to use IDisposable after you are done with it, and you will definitely know when it is no longer needed (the semantics of your class will tell it what you did with it).
  • Your creator will not want to use IDisposable after you finish with it, and you may not know when you will succeed.
  • Your class can be used in some cases, corresponding to (1) above, and in some cases (2), but your creator will know in advance which circumstance applies.
  • Your creator cannot predict whether he will want to continue using the object after you finish with it.

In scenario # 1, you do not need to implement IDisposable, although it might be nice to implement the IDisposable do-nothing handler and use it by consumers if another scenario is to be used in the future.

For scenario # 2, your object must own IDisposable and must dispose of it upon completion. I do not really like when objects take unconditional ownership of IDisposables; I prefer to implement things like in # 3.

There are two ways to handle # 3. The one I prefer is that your object accepts a parameter (either boolean or enumerated) along with IDisposable, indicating whether it should take over the rights to IDisposable. Your class unconditionally implements IDisposable; implementation implements any objects on which she took responsibility, but not those on which she does not have. An alternative is to have two subclasses with a common base class - one subclass implements IDisposable, and the other does not. I prefer the old template, because it allows you to add a method to replace IDisposable with a new one (from which it may or may not belong). For example, if I implemented a control with the Image property, I would have a SetImage method, which with a parameter should indicate whether the control should have a transmitted image; this method will recycle the old image if it belongs to it, and then it can either take responsibility for 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 this is probably for your object to implement IDisposable by raising the Disposed event. Your creator can use this event to delete the object if you used it last, or adjust the flag or counter so that other code knows that this object should not remain without your name.

0
source

All Articles