对成员变量的引用-所有者不受GC约束

本文关键字:GC 约束 所有者 成员 变量 引用 | 更新日期: 2023-09-27 18:26:42

考虑下面的示例(代码)。从Main函数进行对GetA的调用,该调用返回对在函数GetA中创建的对象b的成员变量a的引用。请注意,在GetA返回后,我们不再有对局部变量b最初引用的对象的任何引用。然后我们通过调用GC.Collect()来强制收集。

我可以看到B的最终代码在Main方法的最后一行之前运行,这让我相信下面的代码格式不正确?

问题:下面的代码格式不正确?如果是这样,为什么我们仍然可以访问类型为B的对象的成员a,即使该对象已被销毁/收集?

using System;
class A
{
    public int x = 5;
}
class B
{
    public A a = new A();
    ~B()
    {
        Console.WriteLine("Finalization code running for B.");
    }
}
class Program
{
    static A GetA()
    {
        B b = new B(); // <- Allocate object of type B on the managed heap
        return b.a; // <- We return a (copy-of) reference to a member of B
    }
    static void Main(string[] args)
    {
        A a = GetA();
        // Force a garbage collection
        GC.Collect();
        GC.WaitForPendingFinalizers();
        // This works fine, but is this valid code?
        // "Owner of" a (object of type B allocated in GetA) is dead!
        Console.WriteLine("a.x = {0}", a.x);
    }
}

对成员变量的引用-所有者不受GC约束

为什么我们仍然可以访问类型B 对象的成员a

我们无法访问B.a。我们有权访问一个曾经被B.a引用的对象。

GetA方法中创建的B的实例创建了A的新实例,并将对其的引用存储在B.a字段中。A的这个实例是一个单独的对象,只要它是可访问的,就不会被收集。