C# 如果将泛型集合实例化为包含iDisposable项,这些项是否已被处置?
例如:C# 如果将泛型集合实例化为包含iDisposable项,这些项是否已被处置?,c#,.net,idisposable,C#,.net,Idisposable,例如: Queue<System.Drawing.SolidBrush> brushQ = new Queue<System.Drawing.SolidBrush>(); ... brushQ.Clear(); Queue brushQ=new Queue(); ... brushQ.Clear(); 如果我没有显式地将每个项出列并分别处理它们,那么在调用Clear()时是否会处理剩余的项?队列何时被垃圾收集 假设答案是“不”,那么最佳做法是什么?您是否必须始终遍历队
Queue<System.Drawing.SolidBrush> brushQ = new Queue<System.Drawing.SolidBrush>();
...
brushQ.Clear();
Queue brushQ=new Queue();
...
brushQ.Clear();
如果我没有显式地将每个项出列并分别处理它们,那么在调用Clear()时是否会处理剩余的项?队列何时被垃圾收集
假设答案是“不”,那么最佳做法是什么?您是否必须始终遍历队列并处理每个项目
这可能会变得很糟糕,尤其是如果您必须尝试…最后在每个dispose周围,以防抛出异常
编辑
因此,一般收集的用户似乎有责任知道,如果这些项是一次性的(这意味着它们可能正在使用垃圾收集器无法清理的非托管资源),那么:
也许通用集合的文档应该提到这一点。您希望何时处置它们?集合如何知道其中是否有对对象的其他引用?泛型集合实际上不知道它们所包含的对象类型,因此调用Clear不会导致它们对项目调用Dispose()。一旦集合本身被处理掉,GC最终将处理掉它们,前提是其他任何东西都没有对其中一个项目的活动引用
如果要确保在对集合调用Clear时调用对象的Dispose方法,则需要派生自己的集合并重写适当的方法,然后自己进行调用。正如其他人所说,这不会发生。但是,如果需要,您可以构建自己的扩展方法来处理它们。让我看看是否可以为此编写一个示例代码 编辑: 以下代码实现了IDisposable队列:
class DisposableQueue<T>:Queue<T>,IDisposable where T:IDisposable
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing) {
if (disposing) {
foreach (T type in this) {
try
{
type.Dispose();
}
finally {/* In case of ObjectDisposedException*/}
}
}
}
#endregion
}
class DisposableQueue:Queue,IDisposable其中T:IDisposable
#区域IDisposable成员
公共空间处置()
{
处置(真实);
总干事(本);
}
公共虚拟无效处置(bool处置){
如果(处置){
foreach(此处为T类型){
尝试
{
type.Dispose();
}
最后{/*对于ObjectDisposedException*/}
}
}
}
#端区
}
“GC最终会处理它们…”据我所知,GC不会调用dispose。它将清理托管资源,但任何非托管资源都将保留。不正确。当GC最终开始释放内存时,如果该对象是IDisposable的,GC将处理它。除非brushQ.Clear()后面的行,否则您无法保证何时会发生这种情况;是GC.Collect();。关于这一点:(请参阅本页右侧面板中的“GC会调用IDisposable.Dispose吗?”。@Gwlosa:这不完全正确。如果对象实现IDisposable,只要没有其他引用,GC最终将收集它。如果仍然存在对该对象的活动引用,则不会收集该对象,因为它的容器已被收集。GC从不调用dispose。但是,如果您的类型有终结器,它将调用终结器。如果您正在为库设计自己的泛型队列派生,但如果t是否是一次性的,则不会调用终结器。您是否需要将您的设计分成两个版本:DisposableQueue和NondDisposableQueue?或者在运行时有没有办法确定T是否是一次性的?同样,这是假设没有人持有对您的项目的引用。正如在其他文章中提到的,我想对于通用队列来说,这不是一个好的假设。@mbeckish-正常队列是“不可分发”的。像if(type.GetType()==typeof(IDisposable))这样放置代码听起来不像是一种可靠的编程模式。@mbeckish-拥有IDisposable对象的全部目的是在停止使用资源时释放它们。这取决于你的代码来检查这些资源是否不再被使用。我同意。因此,似乎应该让队列的使用者承担这样的负担:在项目退出队列时进行处理,并在处理完队列后循环队列并处理剩余的项目。对于使用您的队列的开发人员来说,这可能会变得很糟糕。