[英]C# is object valid
您可以检查对象是否为null,但是可以检查对象是否有效吗?
Assert.IsValid(object_name);
例如,垃圾收集器已删除该对象,或者某人已对其进行了处置。 但指针仍然指向该对象。
如果对象已被垃圾收集器释放,则根据定义,您将不会引用该对象。
如果它被处理掉并且对于对象的有效性很重要,那么类型应该提供一种确定它的方法。 (例如,在某些情况下, Dispose
只是意味着“重置”。)
即使允许引用已处置对象的可能性,也很少适用 - 如果您使用:
using (Foo foo = new Foo())
{
...
}
然后该对象将在foo
超出范围的同时被处理,因此这不是问题。
如果对象已被释放,则没有任何“实时”引用,因此您无法访问它(保证没有可读取/写入对象的可访问代码)(这在“安全”代码中......在“不安全”代码中没有任何保证。但由于某种原因它是“不安全的”:-))
对于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();
}
但是如果object_name首先没有被收集,它将如何获取垃圾?
如果指针仍指向对象(根据您的问题),那么对象将无法收集垃圾
将对象存储在WeakReference列表中。
使用IsAlive
属性检查对象是否已被垃圾回收。
根据定义,垃圾收集器不会删除“非垃圾”对象,包括代码保存引用的对象。
由于IDisposable合同不包含这样的方法,因此没有通用的方法来查看对象是否已被处置。 但是许多类都有一种确定其状态的方法,例如SqlConnection类有一个State属性,它将在已处置的对象上返回ConnectionState.Closed。
在GC
和自定义对象状态方面,您只能检查对象是否已使用代数移动
int objectGeneration = GC.GetGeneration(objectInstance)
但你不能访问GCed对象或检查对象是否已被Disposed
因为Dispose()
是每个特定IDisposable
类型的自定义实现,并且在极少数情况下,这些类型暴露了类似IsDisposed标志的东西,因为它对于对象的消费者没有任何意义。在大多数情况下。
当您知道世代号时,您可以根据以下因素做一些假设:
第0代。这是最年轻的一代,包含短期对象。 短期对象的示例是临时变量。 垃圾收集在这一代中最常发生。 新分配的对象形成新一代对象,并且隐式生成0集合,除非它们是大对象,在这种情况下它们在第2代集合中的大对象堆上。 大多数对象在第0代被回收用于垃圾收集,并且不能存活到下一代。
第1代。此代包含短期对象,并用作短期对象和长期对象之间的缓冲区。
第2代。这一代包含长寿命的对象。 长期对象的一个示例是服务器应用程序中的对象,其中包含在进程持续时间内处于活动状态的静态数据
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.