Bobrovsky
Bobrovsky

Reputation: 14246

How to properly design objects with internal references to disposable objects

Suppose, I have following classes:

public class DisposableObj : IDisposable
{
    public ChildObj CreateObj();
    internal object GetSomething();
    // ...
}

public class ChildObj
{
    private DisposableObj m_provider;

    public void DoSomething()
    {
        m_provider.GetSomething();
    }
    // ...
}

It's possible that at some point the disposable object will be disposed but child object will still have a reference to it.

If at this time user will call DoSomething method then child object will try to access disposed object. This is not good hence the question:

How should I properly design such classes?

UPDATE/CLARIFICATION:

I am aware of ObjectDisposedException and all. My question probably should sound like: how to properly notify user about exceptional situation and how design the classes to make maintaining them easier?

Upvotes: 0

Views: 310

Answers (2)

Steve
Steve

Reputation: 216293

First thougth that comes to mind:
Provide your ChildObj class with an internal boolean property called ProviderDisposed.
Set this property to true from Dispose in your DisposableObj

However you should keep a list of the objects created to comunicate to each one the disposed state of your main object.

List<ChildObj> childsCreated = new List<ChildObj>();
public ChildObj CreateObj()
{
    ChildObj obj = new ChildObj();
    childsCreated.Add(obj);
    return obj;
}
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // Check to see if Dispose has already been called.
    if(!this.disposed)
    {
        if(disposing)
        {
            foreach(ChildObj obj in childsCreated)
                obj.ProviderDisposed = true;
            childsCreated = null;
        }
        disposed = true;
    }
}

public class ChildObj   
{   
    private DisposableObj m_provider;   
    private bool m_providerDisposed = false;

    public bool ProviderDisposed 
    { set { m_providerDisposed = true; } }

    public void DoSomething()   
    {   
        if(m_providerDisposed == false)
             m_provider.GetSomething();
        // else // as from **@BrokenGlass answer**
        //     throw new ObjectDisposedException();   
    }   
    // ...   
}  

Upvotes: 2

BrokenGlass
BrokenGlass

Reputation: 160912

While that is a scenario that is technically possible, this should be an exceptional state in your progam - I can't imagine why you would deliberately set up for this scenario.

Having said, that make it clear in your design who is responsible to dispose DisposableObj and when - if any child accesses the disposed object afterwards you can argue that this should cause an exception - don't work around this but throw an exception an let the exception bubble up so you can fix the logic when you discover the problem.

Implementation-wise you can achieve this by just keeping a boolean that keeps track of whether DisposableObj is disposed and on a later access just throw ObjectDisposedException. To clarify I mean the DisposableObj object itself should keep track of its state and throw ObjectDisposedException on any method call on it after it was disposed.

Upvotes: 2

Related Questions