弱引用不被垃圾收集

Jam*_*s B 1 c# weak-references visual-studio

我的理解是,在对Targeta 的所有强引用WeakReference都设置为 null 并调用 GC 后,该弱引用不应再存在。

然而,下面的代码似乎没有遵循这个期望:

    static void Main(string[] _) {
        var person = new Person();
        var wr = new WeakReference(person);

        person = null;

        // We should have access to the person here
        if (wr.Target is Person shouldExist)
        {
            Console.WriteLine($"Person exists! IsAlive: {wr.IsAlive}.");
            shouldExist = null;
        }
        else
        {
            Console.WriteLine($"Person does not exist :( IsAlive: {wr.IsAlive}.");
        }

        // Invoke GC.Collect.            
        GC.Collect();


        if (wr.Target is Person shouldNotExist)
        {
            Console.WriteLine("This person should have been garbage collected");
            Console.WriteLine($"IsAlive: {wr.IsAlive}");
        }
        else
        {
            Console.WriteLine("This person was garbage collected and weak reference is no longer alive");
            Console.WriteLine($"IsAlive: {wr.IsAlive}");
        }
    }
Run Code Online (Sandbox Code Playgroud)

在哪里

class Person
{
    private int mI = 3;
    public int MI { get => mI; set => mI = value; }
}
Run Code Online (Sandbox Code Playgroud)

输出是

人存在!还活着:是的。此人应该已被垃圾收集 IsAlive: True

我期望输出是:

人存在!还活着:是的。此人已被垃圾回收,弱引用已不再存在 IsAlive: False

我在这里遗漏了一些关于弱引用如何工作的内容吗?

Mat*_*son 7

使用对Person对象的引用Main()可以使对象保持活动状态,直到方法结束。

如果按如下方式更改代码(以便在单独的方法中访问对象Person),它将在 C# 12/.NET 8 中按预期工作:

public static class Program                                    
{
    static void Main()
    {
        var wr = getWeakReference();
        checkPersonExists(wr);
        GC.Collect();

        if (wr.Target is Person shouldNotExist)
        {
            Console.WriteLine("This person should have been garbage collected");
            Console.WriteLine($"IsAlive: {wr.IsAlive}");
        }
        else
        {
            Console.WriteLine("This person was garbage collected and weak reference is no longer alive");
            Console.WriteLine($"IsAlive: {wr.IsAlive}");
        }
    }

    static WeakReference getWeakReference()
    {
        var person = new Person();
        var wr     = new WeakReference(person);

        return wr;
    }

    static void checkPersonExists(WeakReference wr)
    {
        // We should have access to the person here
        if (wr.Target is Person)
        {
            Console.WriteLine($"Person exists! IsAlive: {wr.IsAlive}.");
        }
        else
        {
            Console.WriteLine($"Person does not exist :( IsAlive: {wr.IsAlive}.");
        }

    }
}

class Person
{
    private int mI = 3;
    public  int MI { get => mI; set => mI = value; }
}
Run Code Online (Sandbox Code Playgroud)

注意:此行为无法保证,并且在不同版本的 C#/.NET 中可能会有所不同。