Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确设计具有一次性对象内部参照的对象_C#_Idisposable - Fatal编程技术网

C# 如何正确设计具有一次性对象内部参照的对象

C# 如何正确设计具有一次性对象内部参照的对象,c#,idisposable,C#,Idisposable,假设我有以下课程: public class DisposableObj : IDisposable { public ChildObj CreateObj(); internal object GetSomething(); // ... } public class ChildObj { private DisposableObj m_provider; public void DoSomething() { m_provi

假设我有以下课程:

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

public class ChildObj
{
    private DisposableObj m_provider;

    public void DoSomething()
    {
        m_provider.GetSomething();
    }
    // ...
}
有可能在某个时刻一次性对象将被处置,但子对象仍将具有对它的引用

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

我应该如何正确地设计这样的类

更新/澄清:


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

首先想到的是:
为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();   
    }   
    // ...   
}  
List childs created=new List();
public ChildObj CreateObj()
{
ChildObj obj=新的ChildObj();
创建的子项。添加(obj);
返回obj;
}
公共空间处置()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
//检查是否已调用Dispose。
如果(!this.disposed)
{
如果(处置)
{
foreach(childsCreated中的ChildObj对象)
obj.ProviderDisposed=true;
childsCreated=null;
}
这是真的;
}
}
公共类儿童
{   
私人可处置OBJ m_提供商;
private bool m_provider disposed=false;
公共图书馆提供者
{set{m_providerDisposed=true;}}
公共无效剂量测定法()
{   
如果(m_providerDisposed==false)
m_provider.GetSomething();
//else//as from**@BrokenGlass答案**
//抛出新的ObjectDisposedException();
}   
// ...   
}  

首先想到的是:
为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();   
    }   
    // ...   
}  
List childs created=new List();
public ChildObj CreateObj()
{
ChildObj obj=新的ChildObj();
创建的子项。添加(obj);
返回obj;
}
公共空间处置()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
//检查是否已调用Dispose。
如果(!this.disposed)
{
如果(处置)
{
foreach(childsCreated中的ChildObj对象)
obj.ProviderDisposed=true;
childsCreated=null;
}
这是真的;
}
}
公共类儿童
{   
私人可处置OBJ m_提供商;
private bool m_provider disposed=false;
公共图书馆提供者
{set{m_providerDisposed=true;}}
公共无效剂量测定法()
{   
如果(m_providerDisposed==false)
m_provider.GetSomething();
//else//as from**@BrokenGlass答案**
//抛出新的ObjectDisposedException();
}   
// ...   
}  

虽然这在技术上是可行的,但在您的程序中,这应该是一种例外状态-我无法想象您为什么会故意设置此场景

话虽如此,这在您的设计中明确了谁负责dispose
DisposableObj
以及何时-如果任何子对象在之后访问disposed对象,您可以争辩说这会导致异常-不要解决此问题,而是抛出异常,让异常冒泡,以便在发现问题时修复逻辑


在实现方面,您可以通过保持一个布尔值来实现这一点,该布尔值跟踪
DisposableObj
是否被释放,并且在以后的访问中只抛出
ObjectDisposedException
。澄清一下,我的意思是
DisposableObj
对象本身应该跟踪其状态,并在其被释放后对任何方法调用抛出
ObjectDisposedException

虽然这在技术上是可行的,在你的程序中,这应该是一种特殊的状态——我无法想象你为什么会故意设置这种情况

话虽如此,这在您的设计中明确了谁负责dispose
DisposableObj
以及何时-如果任何子对象在之后访问disposed对象,您可以争辩说这会导致异常-不要解决此问题,而是抛出异常,让异常冒泡,以便在发现问题时修复逻辑


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

不可能没有对已释放对象的引用。你不能处理它。正确实现的一次性类引发ObjectDisposedException,您不必帮助。@HansPassant我完全清楚,子对象必须引用父对象。问题是:如何正确地通知用户异常情况,以及如何设计类以使维护它们更容易。不可能没有对已处理对象的引用。你不能处理它。正确实现的一次性类引发ObjectDisposedException,您不必帮助。@HansPassant我完全清楚,子对象必须引用父对象。问题是:如何进行公关