重新创建对“this”的根引用是否合法? 在 .net 析构函数中?
在 .net 中编写以下内容合法吗?
public class A
{
public int i = 0;
~A()
{
Aref = this;
}
}
public static A Aref;
static void Main(string[] args)
{
Aref = new A();
int gen = GC.GetGeneration(Aref);
Aref = null;
GC.Collect(gen, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine(Aref.i);
Console.ReadLine();
}
它可以正常工作并按预期将“0”写入控制台,但我想知道它是否保证始终有效。
有人知道幕后发生了什么吗?
Is it legal to write the following in .net ?
public class A
{
public int i = 0;
~A()
{
Aref = this;
}
}
public static A Aref;
static void Main(string[] args)
{
Aref = new A();
int gen = GC.GetGeneration(Aref);
Aref = null;
GC.Collect(gen, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine(Aref.i);
Console.ReadLine();
}
It works and writes '0' to the console as expected, but I'm wondering if it's guaranteed to always work.
Does someone know what's happening behind the scene?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这就是所谓的复活,而且是合法的。 谷歌搜索“.net 对象复活”(以及类似的术语),您会发现类似以下内容:
复活和 .NET 垃圾收集器
物体复活
只要确保这些僵尸物体不会回来并试图吃掉你的大脑或其他东西即可。 就像所有的死灵术一样,这是危险的东西。 (主要是因为类层次结构中较高层的终结器可以释放一些必要的资源。另请注意,如果对象“未引用”,终结器将不会再次运行,除非您调用 GC.ReRegisterForFinalize代码>.)
It's called resurrection, and it's legal. Google for ".net object resurrection" (and terms like it) and you'll find stuff like:
Resurrection and the .NET Garbage collector
Object Resurrection
Just make sure these zombie objects don't come back and try to eat your brain or something. Like all necromancy, this is dangerous stuff. (Mostly because the finalizers higher up in the class hierarchy can have released some essential resource. Also note that the finalizer won't be run a second time if the object gets "unreferenced", unless you call
GC.ReRegisterForFinalize
.)它之所以有效,是因为第一次垃圾收集不会收集实例。 它只是安排实例运行其终结器。 然后,终结器为该实例创建一个新的根,因此当下一次收集发生时,该实例实际上已建立根,因此无法进行收集。
你应该非常小心这个困难。 如果使用终结器来确保对象被释放,这实际上违反了协议,因为一次性模式规定,如果在释放后使用已释放的实例,则应抛出 ObjectDisposeException。
It works because the first garbage collection doesn't collect the instance. It just schedules the instance to have its finalizer run. The finalizer then creates a new root to the instance, so when the next collection happens the instance is actually rooted and thus not up for collection.
You should be very careful with this tough. If the finalizer is used to make sure an object is disposed, this actually violates the protocol because the disposable patterns says that a disposed instance should throw an ObjectDisposedException if it is used after being disposed.
垃圾收集器将对象分为三组:
Objects cannot be deleted unless there's no rooted reference anywhere. Finalization is a distinct stage before deletion; note that while an object is registered for finalization, all objects it references directly or indirectly will be protected from deletion, but not from finalization.
The garbage collector divides objects into three groups:
Objects cannot be deleted unless there's no rooted reference anywhere. Finalization is a distinct stage before deletion; note that while an object is registered for finalization, all objects it references directly or indirectly will be protected from deletion, but not from finalization.