如何以安全的方式获得弱引用的目标

本文关键字:引用 目标 方式获 安全 | 更新日期: 2023-09-27 17:59:17

考虑以下代码:

var weakRef = new WeakReference(new StringBuilder("Mehran"));
if (weakRef.IsAlive)
{
    // Garbage Collection might happen.
    Console.WriteLine((weakRef.Target as StringBuilder).ToString());
}

GC.Collect可以在检查weakRef.IsAlive之后和使用weakRef.Target之前运行。

我错了吗?如果可能的话,有安全的方法吗?

例如,像weakRef.GetTargetIfIsAlive()这样的API是合适的。

如何以安全的方式获得弱引用的目标

API已经存在;如果对象已经被垃圾回收,则weakRef.Target返回null

StringBuilder sb = weakRef.Target as StringBuilder;
if (sb != null)
{
    Console.WriteLine(sb.ToString());
}

IsAlive属性的存在并不是为了让代码在目标活着的情况下使用它,而是为了让代码知道目标是否已经死亡,但无论如何都不想访问它。如果代码针对null测试Target,这将导致Target暂时具有强根引用(针对null测试的代码),生成这样一个根引用的行为可能会防止对象在其他情况下被垃圾收集。如果代码对Target不感兴趣,只是想知道它是否已经无效,那么代码就没有理由获得引用。它可以简单地测试IsAlive,并在返回false时采取适当的操作。

获取目标的本地副本并检查是否为null。

如果目标已经收集,WeakReference.Target将返回null,但您担心的是它是在.IsAlive检查和获取目标之间收集的。

var weakRef = new WeakReference(new StringBuilder("Mehran"));
if (weakRef.IsAlive)
{
    var stringBuilder = weakRef.Target as StringBuilder;
    if (stringBuilder != null)
    {
        Console.WriteLine(stringBuilder.ToString());
    }
}

如果强制转换失败,Console.WriteLine((weakRef.Target as StringBuilder).ToString());将抛出一个null引用异常。

我相信您要找的是TryGetValue。你的代码应该看起来像:

var weakRef = new WeakReference(new StringBuilder("Mehran"));
if (weakRef.TryGetValue(out StringBuilder sb)
{
    Console.WriteLine(sb.ToString());
}