您可以检查对象是否为null,但是您可以检查对象是否有效吗?
Assert.IsValid(object_name);
例如,垃圾收集器已删除该对象,或者某人已对其进行了处置。但指针仍指向该对象。
答案 0 :(得分:7)
如果对象已被垃圾收集器释放,那么根据定义将不会引用它。
如果它被处理掉并且对于对象的有效性很重要,那么这种类型应该提供一种确定它的方法。 (例如,在某些情况下,Dispose
只能表示“重置”。)
即使允许引用已处置对象的可能性,也很少适用 - 如果您使用:
using (Foo foo = new Foo())
{
...
}
然后该对象将在foo
超出范围的同时处理,因此这不是问题。
答案 1 :(得分:2)
如果对象已被处理,则没有任何“实时”引用,因此您无法访问它(保证没有可读取/写入对象的可访问代码)(在“安全的“代码...在”不安全的“代码中没有任何保证。但它是”不安全“的原因:-))
对于IDisposable
个对象,“正确完成”的类保留了一个标记,它们在每个方法/属性中检查(bool isDisposed = false
开头,isDisposed = true;在Dispose()
)如果对象已经处理好throw new ObjectDisposedException()
。
请注意,C#语言/ .NET运行时中没有任何内容禁止“处置”对象被“重新点燃”,重新使用和“重新处理”,但是代码编写错误(并且支持这种“反模式”,甚至有GC.ReRegisterForFinalize
来平衡GC.SuppressFinalize
中常见的Dispose()
如果您有WeakReference
并且想要检查“仅用于统计目的”,如果仍然可以访问该对象,则使用WeakReference.IsValid
。如果要引用对象以使用它,可以使用WeakReference.Target
并检查返回值是否为null
。这非常重要!!
var wr = new WeakReference(new List<int>());
// Right!!
var target = (List<int>)wr.Target;
if (target != null)
{
target.Clear();
}
// Wrong!! The GC could kick in after the if and before the target =
if (wr.IsAlive)
{
target = (List<int>)wr.Target;
target.Clear();
}
答案 2 :(得分:1)
但是如果object_name首先没有被清空,它将如何收集垃圾?
如果指针仍指向对象(根据您的问题),那么对象将无法收集垃圾
答案 3 :(得分:0)
将您的对象存储在WeakReference的列表中。
使用IsAlive
属性检查对象是否已被垃圾回收。
答案 4 :(得分:0)
根据定义,垃圾收集器不会删除“非垃圾”的对象,包括代码保存引用的对象。
由于IDisposable合同不包含此类方法,因此无法查看是否已处置对象。但是许多班级都有办法确定他们的状态,例如: SqlConnection类有一个State属性,它将在已处置的对象上返回ConnectionState.Closed。
答案 5 :(得分:0)
就GC
和自定义对象状态而言,您只能使用
int objectGeneration = GC.GetGeneration(objectInstance)
但您无法访问GCed对象或检查对象是否为Disposed
,因为Dispose()
是每种特定IDisposable
类型的自定义实现,并且在极少数情况下,这些类型会暴露出类似IsDisposed标志,因为在大多数情况下它对对象的消费者没有任何意义。
当您知道世代号时,您可以根据以下内容做一些假设:
Fundamentals of Garbage Collection: Generations
第0代。这是最年轻的一代,包含短期对象。短期对象的一个例子是临时的 变量。垃圾收集最常发生在此 代。新分配的对象形成新一代对象 并且是隐式生成0集合,除非它们很大 对象,在这种情况下,它们在一个大的对象堆上 第2代收藏。大多数物体都被回收用于垃圾 在第0代收集并且不能存活到下一代。
第1代。此代包含短期对象,并充当短期对象和长期对象之间的缓冲区。
第2代。此代包含长寿命对象。长期存在的对象的示例是服务器应用程序中的对象 包含在过程期间有效的静态数据