如何正确设计具有对一次性对象的内部引用的对象

时间:2012-03-17 14:36:38

标签: c# idisposable

假设我有以下课程:

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

public class ChildObj
{
    private DisposableObj m_provider;

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

在某些时候,可能会丢弃一次性物体,但是儿童物体仍然可以参考它。

如果此时用户将调用DoSomething方法,则子对象将尝试访问已处置的对象。这不好,因此问题:

我应该如何正确设计这些类?

UPDATE /澄清:

我知道ObjectDisposedException和所有。我的问题可能听起来像:如何正确地通知用户有关异常情况以及如何设计类以使其更容易维护?

2 个答案:

答案 0 :(得分:2)

首先想到的是:
为您的ChildObj类提供一个名为ProviderDisposed的内部布尔属性 从DisposableObj中的Dispose将此属性设置为true

但是,您应该保留一个创建的对象列表,以便为每个对象提供主对象的处置状态。

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();   
    }   
    // ...   
}  

答案 1 :(得分:2)

虽然这是技术上可行的场景,但这应该是你的程序中的特殊状态 - 我无法想象为什么你会故意为这个场景设置。

说完了,在你的设计中明确谁负责处理DisposableObj以及何时 - 如果有任何孩子随后访问处置的对象你可以争辩说这个应该导致异常 - 不要解决这个问题,但抛出异常,让异常冒泡,以便在发现问题时修复逻辑。

实现方面,您可以通过保留一个布尔值来实现这一点,该布尔值可以跟踪DisposableObj是否被处置,以及稍后的访问只是抛出ObjectDisposedException。澄清我的意思是DisposableObj对象本身应该跟踪它的状态,并在它被处理后抛出ObjectDisposedException对它的任何方法调用。