Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I safely clean up after a readonly object field?

Let's say I have a class with a object field. When Dispose() is called I would like to clear the reference to that object. The private field can only be set once, so ideally I would like it to be readonly, but if it is readonly there is a compile time error when I try to release the reference to the object during Dispose(). Ideally I would like to have a safe dispose AND mark the _value field as readonly. Is this possible or even necessary?

public class Foo : IDisposable
{
      public Foo(object value)
      {
            _value = value;
      }

      public object Value { get { return _value; } }
      private readonly object _value;

      public void Dispose()
      {
            //Cleanup here
            _value = null     // causes compile time error
      }
}
like image 384
cordialgerm Avatar asked Oct 22 '10 02:10

cordialgerm


4 Answers

That's not necessary, even if it were possible.

Dispose is typically intended to clean up unmanaged resources, although there can be exceptions to that rule (note the comments). However, in this situation, you should allow the garbage collector to do its job. It will run indeterminately once the objects are considered to have no active roots. Under normal circumstances, you do not need to take action to force it. Just write your code with objects in properly limited scope and you will be fine.

like image 168
Anthony Pegram Avatar answered Sep 21 '22 11:09

Anthony Pegram


Setting the reference to null does not in fact do anything. The garbage collector will clean up the object when there are no longer any references to it, which in this case since you are doing this in the Dispose method presumably the instance of Foo is about to no longer have any references to it and the difference in timing is probably not meaningful. Typically you implement the Dispose pattern because your type has as a member a class that itself implements IDisposable (in this case the type is Object, which does not implement IDisposable), or you have unmanaged resources that you would like to release deterministically. You can find a description of the Dispose pattern here. Note that if you create a readonly member variable of a type that implements IDisposable you can call the Dispose method on that object inside your Dispose method:

public class SomeClass : IDisposable
{
    private Boolean mDisposed;
    private readonly MemoryStream mStream = new MemoryStream(); // Could be any class that implements IDisposable
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected void Dispose(Boolean disposing) {
        if (disposing & !mDisposed) {
            mStream.Dispose();  // Could and should call Dispose
            mDisposed = true;
        }
        return;
    }
}

This works because the readonly nature is on the reference to the object, not the object itself.

like image 23
Steve Ellinger Avatar answered Sep 17 '22 11:09

Steve Ellinger


That is not necessary nor correct. Wanting to do what you ask in your question seems to indicate you are somewhere accessing a disposed object, and that is wrong.

Rather than try to do what you have asked, you should perhaps implement IsDisposed (which btw is part of the standard Dispose pattern) and check it first.

As others have noted, the Dispose pattern is intended for releasing unmanaged resources.

like image 44
Mitch Wheat Avatar answered Sep 21 '22 11:09

Mitch Wheat


This is an older post, but I face the same question regularly because I unsubscribe from objects that I subscribed to.

I do this unsubscription during dispose because those objects live longer than this object, and the way delegates are implemented means that the publisher keeps the subscriber alive, not the other way around like we would think.

BUT, when you unsubscribe from the events, you have the natural tendency to want to clear the reference to the publisher too, which really isn't such a big deal. I suggest you keep the 'readonly' constraint because it makes the rules clearer and the code more robust while the object is still alive. If it means you sit with the reference after dispose, that is okay becuase the object is now collectible.

like image 32
Martin Lottering Avatar answered Sep 17 '22 11:09

Martin Lottering