8

考虑这段代码:

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.

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

例如,类似的 APIweakRef.GetTargetIfIsAlive()将是合适的。

4

4 回答 4

12

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

StringBuilder sb = weakRef.Target as StringBuilder;
if (sb != null)
{
    Console.WriteLine(sb.ToString());
}
于 2013-02-13T15:17:15.423 回答
10

IsAlive属性的存在不是为了代码的利益,如果它是活着的,它会想要使用目标,而是为了代码的利益,它想要找出目标是否已经死亡,但不会有兴趣以任何方式访问它案子。如果代码要Target针对 null 进行测试,那将导致Target暂时具有强根引用(针对 null 进行测试的代码),并且生成这种根引用的行为可能会阻止对象在它被垃圾收集时否则会。如果代码不感兴趣,Target只是想知道它是否已经失效,那么代码就没有理由获取引用。它可以简单地进行测试IsAlive,并在返回时采取适当的措施false

于 2013-02-27T22:55:08.217 回答
1

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

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());如果转换失败,将抛出空引用异常。

于 2013-02-13T15:19:50.433 回答
0

我相信您正在寻找的是TryGetValue. 您的代码应如下所示:

var weakRef = new WeakReference(new StringBuilder("Mehran"));
if (weakRef.TryGetValue(out StringBuilder sb)
{
    Console.WriteLine(sb.ToString());
}
于 2018-11-16T22:55:15.497 回答