我的理解是,在对WeakReferenceTarget的所有强引用设置为空并调用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}");
        }
    }

哪里

class Person
{
    private int mI = 3;
    public int MI { get => mI; set => mI = value; }
}

输出结果是

Person exists! IsAlive: True. This person should have been garbage collected IsAlive: True

我原以为输出为:

Person exists! IsAlive: True. This person was garbage collected and weak reference is no longer alive IsAlive: False

我在这里错过了一些关于弱引用如何工作的东西吗?

推荐答案

使用Main()中对Person对象的引用使该对象保持活动状态,直到方法结束.

如果您按如下方式更改代码(以便在单独的方法中访问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; }
}

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

Csharp相关问答推荐

访问C#中的数据库字段时获取数据是收件箱错误-为什么?&有效,如果声明不有效

无法将blob发送到Azure -缺少HTTP标头异常

AutoMapper -如何为两个不同的用例设置单个映射?

一小时后,自定义缓存停止在App Insight中保存

为什么我的ASP.NET核心MVC应用程序要为HTML元素添加一些标识符?

是否可以使用EF—Core进行临时部分更新?

dotnet集合中内部数组的局部变量副本的用途是什么?'

ASP.NET核心REST API返回一个非常大的数字

如何在没有前缀和可选后缀的情况下获取Razor Page Handler方法名称?

C#阻塞调用或await calling inside calling方法

C#无法让WinForm进度条生成动画错误跨线程操作无效

为基本审计设置Audit.EntityFramework.Core

如何让NLog停止写入冗余信息?

当我没有此令牌时,为什么语法报告EOF错误?

有没有类似于扩展元素的合并元组的语法?

升级后发出SWITCH语句

Blazor Server/.NET 8/在初始加载时调用异步代码是否冻结屏幕,直到第一次异步调用完成?

从GRPC连接创建ZipArchive

流畅的验证--如何为属性重用规则?

从MudAutoComplete打开对话框,列表仍然可见