1

I'm sorry if this is a stupid question but after you have explicitly disposed of an object, you should not be referencing that object again... right?

Example: This is generally a bad idea right?

SomeObject o = new SomeObject();

o.DoStuff();

o.Dispose();

o.DoMoreStuff();

Also, is there ever a situation where doing something like this is necessary?

user1451495
  • 309
  • 3
  • 5
  • 9
  • 6
    Small clarification. It is not generally a bad idea. It is always a bad idea. If you still need to use the object it should not have been disposed of. – linuxuser27 Jun 20 '12 at 16:04
  • 3
    Do you normally put food in the garbage can then pull it back out to eat it later? – Gabe Jun 20 '12 at 16:06
  • 3
    @Gabe - Sometimes I forget to buy groceries. – ChaosPandion Jun 20 '12 at 16:07
  • @ChaosPandion, lol, that's stinks! literally! – Gabe Jun 20 '12 at 16:07
  • More info on dispose in this [question](http://stackoverflow.com/questions/5895879/when-do-we-need-to-call-dispose-in-dot-net-c). – user17753 Jun 20 '12 at 16:13
  • 1
    @linuxuser27: not true. There are scenarios (rare and usually hidden form public view) where this makes sense. So the OPs 'generally' is more accurate than 'always'. – H H Jun 20 '12 at 16:27
  • @HenkHolterman I agree in the sense that 'always' is a strong word to use, but in this case implementing `Dispose` is apart of a contract and good design would follow that contract. I can think of scenarios to use it as well, but in my mind they are predicated on a flaw application architecture. – linuxuser27 Jun 20 '12 at 17:39

4 Answers4

2

You will never Dispose an object till you need it. Disposing an object means you don't need that anymore. And when you don't need the object anymore you will dispose it (if it is disposable). So there's never a point of accessing an object after it is disposed.

this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
  • There are many situations where may wish to retrieve information from an object after the point where all its resources could be released. Deferring the `Dispose` until all necessary information is retrieved (which might happen in a different application layer from the one which finds out that the object's resources could be released--see `ShowDialog`) may often be less clean than simply letting the inner layer acquire a resource, use it to collect information, and release the resource, while leaving the object in a state where the collected information remains available to the caller. – supercat Jun 21 '12 at 17:03
  • Then this is a Design related issue and it has nothing to do with Disposed object. The basic rule of thumb is you will dispose the object after you're done with it for everything you want it do including object information retrieval in your case. – this. __curious_geek Jun 22 '12 at 07:19
  • Certainly one approach to avoid the issue would be to have an `IDisposable` object be bound somehow to a non-disposable object which would maintain the information that should persist beyond the lifetime of the `IDisposable` object. For example, a modeless `FindAndReplaceDialog` box could hold a reference to a `FindAndReplaceParams` object which the dialog box would keep updated. If the object is not created by the box itself, though, the semantics could be murky if the same object were assigned to two dialog boxes; if the object is created by the box itself, it would seem irksome to... – supercat Jun 22 '12 at 15:20
  • ...require that a reference to that object be grabbed before the `Dispose`. Thinking about it, though, perhaps a reasonable approach would be to have information which should be available kept encapsulated into an object which would be created when the `IDisposable` was created, a reference to which would "forevermore" be available as an immutable property? That way it would be clear what information was guaranteed to remain available and what information was not. – supercat Jun 22 '12 at 15:23
2

Disposing of an object tells it to release all of it's unmanaged resources, so the question that you have to ask yourself is "can the object do anything meaningful without those resources". That will depend on the specifics of the object.

Most IDisposable objects are designed such that if you try to call their methods after disposing the instance they will throw an exception, or worse, just do unexpected behavior.

It's possible for other object to still have meaningful things to do even after being disposed. As an example, a DataTable implements IDisposable, but the meaningful data tends to be stored in managed resources, not unmanaged resources. In its current implementation (which is subject to change) its Dispose method doesn't do anything, so using it after it is disposed is just fine. (Having said that, there is no compelling reason to dispose it when you still plan to use it.)

It's also conceivable for an object to re-create whatever resource it needs after it has been disposed (that would be a bad idea, but still possible).

Having said all of that, it is considered bad practice to specifically design an object that you intend to be used even after it has been disposed, and it is also the intent of a Disposable object that you not dispose of it until you're done with it. The point here is that even though you shouldn't do it, and it will often blow up in your face, it will be because that's how the class was chosen to be implemented (to be in line with convention) not because it's a technical requirement.

Servy
  • 202,030
  • 26
  • 332
  • 449
0

Although in theory there is absolutely nothing stopping you from creating a class that allows you to dispose and then continue to use that object, I can't think of a single situation where this would be desirable (other than checking to see if the object has been disposed, e.g. IsDisposed).

Normally the pattern used is to simply throw away disposed objects, and re-create them if necessary, in fact in many cases attempting to access a disposed object will result in an ObjectDisposedException being thrown. If you are creating an object that implements IDisposable then it would be a good idea to follow this convention.

To help keep track of what objects have and haven't been disposed (as well an ensuring that your objects are disposed, even in the case of an exception being thrown), use the using statement:

using (SomeObject o = new SomeObject())
{
    o.DoStuff();
}
Justin
  • 84,773
  • 49
  • 224
  • 367
  • A pattern that allowed one to read the contents of a form after it was disposed would have been better than a pattern which required all information to be read from a form before it's disposed (which in turn requires that `ShowDialog` leave forms in a closed-but-not-disposed state). – supercat Jun 21 '12 at 16:51
  • @supercat Windows Forms is simply a wrapper around the Win32 API - once a form has been disposed the window handle has been cleaned up and so any information that is based on the Win32 API (such as the form dimensions) is simply not available any more as those functions require a valid window handle. – Justin Jun 21 '12 at 17:01
  • Generally, I would expect that when a form is closed, the code for the form would know which properties of the form or its controls will continue to be of interest, and could thus ensure that those properties were persisted somehow. Some similar issues exist if one wishes to close a socket connection cleanly and then process all information which was exchanged prior to the close. One could use the sequence `Close`, `Read`, `Dispose`, but I dislike requiring a `Close` before `Dispose` in cases where the `Close` could perform all of the essential actions of `Dispose`. – supercat Jun 21 '12 at 18:07
0

I like to use this pattern when implementing IDisposable...

private bool m_disposed;

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

public void Dispose(bool disposing)
{
    if (!m_disposed)
    {
        if (disposing)
            // Cleanup and close resources

        m_disposed = true;
    }
}

then in all my other methods within the class I will do this...

public void DoMoreStuff()
{
    if (m_disposed)
        throw new ObjectDisposedException();

  // Your code here
}

public void DoStuff()
{
    if (m_disposed)
        throw new ObjectDisposedException();

    // Your code here
 }
Gene S
  • 2,735
  • 3
  • 25
  • 35