简体   繁体   English

C#是对象有效的

[英]C# is object valid

You can check if an object is null but can you check if an object is valid? 您可以检查对象是否为null,但是可以检查对象是否有效吗?

Assert.IsValid(object_name);

For example, the object has been deleted by the garbage collector or someone has done dispose on it. 例如,垃圾收集器已删除该对象,或者某人已对其进行了处置。 But the pointer is still pointing to that object. 但指针仍然指向该对象。

If the object has been freed by the garbage collector, you won't have a reference to it, by definition. 如果对象已被垃圾收集器释放,则根据定义,您将不会引用该对象。

If it's been disposed and that's important to the object's validity, the type ought to provide a way of determining that. 如果它被处理掉并且对于对象的有效性很重要,那么类型应该提供一种确定它的方法。 (In some cases Dispose can just mean "reset", for example.) (例如,在某些情况下, Dispose只是意味着“重置”。)

It's rarely appropriate to even allow the possibility of having a reference to a disposed object though - if you use: 即使允许引用已处置对象的可能性,也很少适用 - 如果您使用:

using (Foo foo = new Foo())
{
    ...
}

then the object will be disposed at the same time that foo goes out of scope, so this isn't an issue. 然后该对象将在foo超出范围的同时被处理,因此这不是问题。

If the object has been disposed, there isn't any "live" reference of it, so you can't access it (it's guaranteed that there is no reachable code that can read/write the object) (this in "safe" code... In "unsafe" code there isn't any guarantee of anything. But it's "unsafe" for a reason :-) ) 如果对象已被释放,则没有任何“实时”引用,因此您无法访问它(保证没有可读取/写入对象的可访问代码)(这在“安全”代码中......在“不安全”代码中没有任何保证。但由于某种原因它是“不安全的”:-))

For the IDisposable objects, classes "correctly done" keep a flag that they check ( bool isDisposed = false at the beginning, isDisposed = true; in the Dispose() ) in every method/property and if the object is already disposed they throw new ObjectDisposedException() . 对于IDisposable对象,“正确完成”类保留了一个标志,它们在每个方法/属性中检查( bool isDisposed = false ,在开头,isDisposed = true;在Dispose() ),如果对象已经被处理,则它们会throw new ObjectDisposedException()

Note that there isn't anything in the C# language/.NET runtime that forbids for a "disposed" object to be "reignited", reused and "re-disposed" again, but it is bad code writing (and to support this "anti-pattern" there is even a GC.ReRegisterForFinalize to balance the GC.SuppressFinalize often done in Dispose() ) 请注意,C#语言/ .NET运行时中没有任何内容禁止“处置”对象被“重新点燃”,重新使用和“重新处理”,但是代码编写错误(并支持此“反模式“甚至还有一个GC.ReRegisterForFinalize来平衡GC.SuppressFinalize经常在Dispose()完成

If you have a WeakReference and you want to check "only for statistical purpose" if the object is still reachable, you use WeakReference.IsValid . 如果您有WeakReference并且您想要检查“仅用于统计目的”,如果仍然可以访问该对象,则使用WeakReference.IsValid If you want a reference to the object to use it, you use WeakReference.Target and check if the return value is null . 如果要引用对象以使用它,可以使用WeakReference.Target并检查返回值是否为null This is very important!! 这个非常重要!!

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();
}

but how would object_name get garbage collected if its not nulled first? 但是如果object_name首先没有被收集,它将如何获取垃圾?

If a pointer is still pointing to the object (per your question) then there is no way the object will get garbage collected 如果指针仍指向对象(根据您的问题),那么对象将无法收集垃圾

Store your objects in a list of WeakReference 's. 将对象存储在WeakReference列表中。

Use the IsAlive property to check if the object has been garbage collected. 使用IsAlive属性检查对象是否已被垃圾回收。

The garbage collector does by definition not delete objects that are "not garbage", that includes objects to which your code holds a reference. 根据定义,垃圾收集器不会删除“非垃圾”对象,包括代码保存引用的对象。

There is no general way to see if an object has been disposed, as the IDisposable contract does not contain such a method. 由于IDisposable合同不包含这样的方法,因此没有通用的方法来查看对象是否已被处置。 But many classes have a way of determining their state, eg the SqlConnection class has a State property which will return ConnectionState.Closed on a disposed object. 但是许多类都有一种确定其状态的方法,例如SqlConnection类有一个State属性,它将在已处置的对象上返回ConnectionState.Closed。

In terms of GC and a custom object state you can only check whether object has been moved across the generations using GC和自定义对象状态方面,您只能检查对象是否已使用代数移动

int objectGeneration = GC.GetGeneration(objectInstance)

but you can not access GCed object or check whether object was Disposed because Dispose() is a custom implementation of the each particular IDisposable type and in very rare cases those types exposed something like IsDisposed flag because it does not make any sense for object's consumer in most cases. 但你不能访问GCed对象或检查对象是否已被Disposed因为Dispose()是每个特定IDisposable类型的自定义实现,并且在极少数情况下,这些类型暴露了类似IsDisposed标志的东西,因为它对于对象的消费者没有任何意义。在大多数情况下。

When you know a generation number you can do some assumptions based on: 当您知道世代号时,您可以根据以下因素做一些假设:

Fundamentals of Garbage Collection: Generations 垃圾收集的基本原理:世代

Generation 0. This is the youngest generation and contains short-lived objects. 第0代。这是最年轻的一代,包含短期对象。 An example of a short-lived object is a temporary variable. 短期对象的示例是临时变量。 Garbage collection occurs most frequently in this generation. 垃圾收集在这一代中最常发生。 Newly allocated objects form a new generation of objects and are implicitly generation 0 collections, unless they are large objects, in which case they go on the large object heap in a generation 2 collection. 新分配的对象形成新一代对象,并且隐式生成0集合,除非它们是大对象,在这种情况下它们在第2代集合中的大对象堆上。 Most objects are reclaimed for garbage collection in generation 0 and do not survive to the next generation. 大多数对象在第0代被回收用于垃圾收集,并且不能存活到下一代。

Generation 1. This generation contains short-lived objects and serves as a buffer between short-lived objects and long-lived objects. 第1代。此代包含短期对象,并用作短期对象和长期对象之间的缓冲区。

Generation 2. This generation contains long-lived objects. 第2代。这一代包含长寿命的对象。 An example of a long-lived object is an object in a server application that contains static data that is live for the duration of the process 长期对象的一个​​示例是服务器应用程序中的对象,其中包含在进程持续时间内处于活动状态的静态数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM