C# 对象有效

发布于 2024-12-12 05:15:39 字数 137 浏览 0 评论 0原文

你可以检查一个对象是否为空,但你能检查一个对象是否有效吗?

Assert.IsValid(object_name);

例如,该对象已被垃圾收集器删除或有人对其进行了处理。但指针仍然指向该对象。

You can check if an object is null but can you check if an object is valid?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

荒芜了季节 2024-12-19 05:15:39

如果该对象已被垃圾收集器释放,那么根据定义,您将不会拥有对它的引用。

如果它已被处理并且这对于对象的有效性很重要,则该类型应该提供一种确定该情况的方法。 (例如,在某些情况下,Dispose 只能表示“重置”。)

尽管如此,甚至允许引用已处置对象的可能性也是不合适的 - 如果您使用:

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

则该对象将被在 foo 超出范围的同时进行处理,因此这不是问题。

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.)

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.

铁憨憨 2024-12-19 05:15:39

如果该对象已被释放,则没有任何对它的“实时”引用,因此您无法访问它(保证没有可访问的代码可以读/写该对象)(这在“安全”代码中...在“不安全”代码中,没有任何保证,但它是“不安全”的,这是有原因的:-) )

对于 IDisposable 对象,“正确完成”的类保留一个标志:他们检查(bool isDispose = false 在开头,isDispose = true; 在 Dispose() 中)在每个方法/属性中,如果对象已经被释放,它们会抛出新的ObjectDisposeException()。

请注意,C# 语言/.NET 运行时中没有任何内容禁止“重新点燃”、重用和再次“重新处置”“已处置”对象,但这是糟糕的代码编写方式(并支持这种“反模式”,甚至还有一个 GC.ReRegisterForFinalize 来平衡通常在 Dispose() 中完成的 GC.SuppressFinalize

如果您有一个 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();
}

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().

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

If you have a WeakReference and you want to check "only for statistical purpose" if the object is still reachable, you use 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. 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();
}
橘亓 2024-12-19 05:15:39

但是如果 object_name 不首先被清空,那么它如何被垃圾回收呢?

如果指针仍然指向该对象(根据您的问题),那么该对象将无法被垃圾收集

but how would object_name get garbage collected if its not nulled first?

If a pointer is still pointing to the object (per your question) then there is no way the object will get garbage collected

得不到的就毁灭 2024-12-19 05:15:39

将对象存储在 WeakReference 列表中。

使用 IsAlive 属性检查对象是否已被垃圾回收。

Store your objects in a list of WeakReference's.

Use the IsAlive property to check if the object has been garbage collected.

拥醉 2024-12-19 05:15:39

根据定义,垃圾收集器不会删除“非垃圾”对象,其中包括代码所引用的对象。

没有通用的方法来查看对象是否已被释放,因为 IDisposable 合约不包含这样的方法。但许多类都有一种确定其状态的方法,例如,SqlConnection 类有一个 State 属性,它将在已处置的对象上返回 ConnectionState.Closed。

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. But many classes have a way of determining their state, e.g. the SqlConnection class has a State property which will return ConnectionState.Closed on a disposed object.

音盲 2024-12-19 05:15:39

GC和自定义对象状态而言,您只能检查对象是否已跨代移动

int objectGeneration = GC.GetGeneration(objectInstance)

,但无法访问GCed对象或检查对象是否已Dispose,因为Dispose() 是每个特定 IDisposable 类型的自定义实现,在极少数情况下,这些类型会公开类似 IsDispose 标志的内容,因为它对于对象的使用者没有任何意义大多数情况下。

当您知道代号时,您可以根据以下内容进行一些假设:

垃圾基础知识收藏:世代

第 0 代。这是最年轻的一代,包含寿命较短的对象。短期对象的一个​​例子是临时对象
多变的。垃圾收集最常发生在这个领域
一代。新分配的对象形成新一代对象
和 是隐式第 0 代集合,除非它们很大
对象,在这种情况下,它们位于大对象堆上
第 2 代集合。大多数对象都被回收为垃圾
在第 0 代中收集,并且不会保存到下一代。

第 1 代。这一代包含短寿命对象,并充当短寿命对象和长寿命对象之间的缓冲区。

第 2 代。 这一代包含长期存在的对象。长寿命对象的一个​​示例是服务器应用程序中的对象
包含在处理期间有效的静态数据

In terms of GC and a custom object state you can only check whether object has been moved across the generations using

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.

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. 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. Most objects are reclaimed for garbage
collection in generation 0 and do not survive to the next generation.

Generation 1. This generation contains short-lived objects and serves as a buffer between short-lived objects and long-lived objects.

Generation 2. This generation contains long-lived objects. 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文