C#怎么使用弱引用WeakReference C# WeakReference避免内存泄漏

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

在 C# 中,

WeakReference
主要用于缓存、事件监听器管理或对象图中存在循环引用的场景,它让 GC 可以在内存紧张时回收目标对象,从而避免强引用导致的内存泄漏。

WeakReference 的核心作用:不阻止垃圾回收

普通引用(如

var obj = new MyClass();
)是强引用,只要还有强引用存在,GC 就不会回收该对象。
WeakReference
则不同——它“弱弱地”指向一个对象,不计入 GC 的可达性判断。只要没有其他强引用,哪怕这个
WeakReference
还活着,目标对象也可能被回收。

基本用法:创建、获取、检查是否存活

推荐使用泛型版本

WeakReference<t></t>
(.NET 4.5+),类型安全且无需装箱:

创建:
var weakRef = new WeakReference<list>>(new List<int> { 1, 2, 3 });</int></list>
尝试获取值:
if (weakRef.TryGetTarget(out var list)) { /* list 不为 null,可用 */ }
检查是否已回收:
bool isAlive = weakRef.TryGetTarget(out _);

非泛型

WeakReference
仍可用,但需手动类型转换和处理
IsAlive
+
Target
(注意竞态风险,
IsAlive
返回 true 后
Target
仍可能为 null)。

典型防泄漏场景:缓存与事件订阅

缓存小对象(如 UI 资源、解析结果):

Dictionary<string weakreference>></string>
缓存图片,内存不足时自动释放,下次访问时按需重建,不阻塞 GC。

解除事件订阅泄漏(尤其跨生命周期):
例如窗体 A 订阅了静态类或长生命周期服务的事件,A 关闭后若未取消订阅,会因委托持有 A 的强引用而无法回收。
可改用弱事件模式(如

WeakEventManager
),或自定义弱代理包装器,让事件源不强引用订阅者。

注意事项:别把它当“自动空安全”

TryGetTarget
是线程安全的,但获取到的对象仍可能被其他线程释放(不过 .NET GC 是全局暂停的,实际中极少发生“刚拿到就变 null”)
不要对同一对象同时持有强引用和弱引用并依赖弱引用来“延缓释放”——这违背设计初衷,也起不到释放效果 频繁调用
TryGetTarget
并反复重建对象,可能抵消弱引用带来的内存优势,应结合业务权衡

基本上就这些。WeakReference 不复杂,但容易忽略它的“非确定性”——你不能假设它总能取到值,也不能靠它来精确控制生命周期。合理用在缓存、解耦、破循环引用上,才是避免内存泄漏的关键。

相关推荐