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();
}
// ...
}
虽然这在技术上是可行的,但在您的程序中,这应该是一种例外状态-我无法想象您为什么会故意设置此场景
话虽如此,这在您的设计中明确了谁负责disposeDisposableObj
以及何时-如果任何子对象在之后访问disposed对象,您可以争辩说这会导致异常-不要解决此问题,而是抛出异常,让异常冒泡,以便在发现问题时修复逻辑
在实现方面,您可以通过保持一个布尔值来实现这一点,该布尔值跟踪
DisposableObj
是否被释放,并且在以后的访问中只抛出ObjectDisposedException
。澄清一下,我的意思是DisposableObj
对象本身应该跟踪其状态,并在其被释放后对任何方法调用抛出ObjectDisposedException
。虽然这在技术上是可行的,在你的程序中,这应该是一种特殊的状态——我无法想象你为什么会故意设置这种情况
话虽如此,这在您的设计中明确了谁负责disposeDisposableObj
以及何时-如果任何子对象在之后访问disposed对象,您可以争辩说这会导致异常-不要解决此问题,而是抛出异常,让异常冒泡,以便在发现问题时修复逻辑
在实现方面,您可以通过保持一个布尔值来实现这一点,该布尔值跟踪
DisposableObj
是否被释放,并且在以后的访问中只抛出ObjectDisposedException
。澄清一下,我的意思是DisposableObj
对象本身应该跟踪它的状态,并在它被释放后对它的任何方法调用抛出ObjectDisposedException
。不可能没有对已释放对象的引用。你不能处理它。正确实现的一次性类引发ObjectDisposedException,您不必帮助。@HansPassant我完全清楚,子对象必须引用父对象。问题是:如何正确地通知用户异常情况,以及如何设计类以使维护它们更容易。不可能没有对已处理对象的引用。你不能处理它。正确实现的一次性类引发ObjectDisposedException,您不必帮助。@HansPassant我完全清楚,子对象必须引用父对象。问题是:如何进行公关