c# weakreference 弱引用有什么用

来源:这里教程网 时间:2026-02-21 17:39:10 作者:

WeakReference 的核心用途是:在不阻止 GC 回收的前提下,临时“惦记着”一个对象——它不是为了长期持有,而是为了“有就用,没了再建”。

WeakReference
最典型的使用场景

它不是万能胶,而是专治几类特定问题的“止痛贴”:

大对象缓存:比如一个 50MB 的图像预处理结果、一棵深层嵌套的树视图数据。用户切走页面后,你不想强留它占内存,但返回时又希望“如果还在,就直接用”,
WeakReference
正好卡在这个平衡点。
事件监听器防泄漏:UI 控件订阅了 ViewModel 的事件,但 ViewModel 生命周期更长。若不手动
Unsubscribe
,控件就永远被强引用链拴住——改用弱引用管理订阅者(需配合自定义事件代理),可让控件随 UI 一起被回收。
避免循环引用导致的内存滞留:父对象持子对象强引用没问题,但子对象反过来强引用父对象,就容易形成 GC 不动的“孤岛”。把子→父的引用换成
WeakReference
,就能打破僵局。

WeakReference
的两个构造函数参数差异很关键

别只用无参构造!

trackResurrection
这个布尔值决定的是“对象被终结器复活后,弱引用还作不作数”:

new WeakReference(obj)
→ 短弱引用(
GCHandleType.Weak
):终结器执行前就清空
Target
。对象一旦进 finalization 队列,你就再也拿不到它了。
new WeakReference(obj, true)
→ 长弱引用(
GCHandleType.WeakTrackResurrection
):即使对象被
GC.ReRegisterForFinalize(this)
复活,
Target
仍可能非 null
(但极罕见,且不可靠)。

绝大多数业务场景选默认(

false
)就够了;除非你在写底层框架、对象池,且明确需要感知复活状态,否则加
true
只会增加不确定性。

访问
Target
前必须检查,否则必崩

这是新手踩坑最密集的地方:弱引用不是“延迟加载”,而是“随时可能消失”。下面这段代码看着合理,实则危险:

var weak = new WeakReference(myBigObject);
// ... 一段时间后
var obj = weak.Target as MyType; // ❌ Target 可能已是 null!
obj.DoSomething(); // NullReferenceException!

正确姿势永远是:

if (weak.TryGetTarget(out MyType obj))
{
    obj.DoSomething(); // ✅ 安全
}
else
{
    // 重建或跳过
}

注意:

IsAlive
属性已过时(.NET 5+ 标记为 obsolete),它不能保证
Target
非 null —— 因为 GC 可能在
IsAlive == true
后瞬间回收对象,紧接着
Target
就变 null。所以务必用线程安全的
TryGetTarget

真正难的不是写对那几行代码,而是想清楚:这个对象“值得弱引用吗?”——太小(如

int
包装、短字符串)不值得;重建成本太高(如需远程调用 DB 初始化)也不适合;只有“大 + 易重建 + 访问频次低”的对象,才配得上
WeakReference
这张牌。

相关推荐