WeakReference 是 C# 中不阻止 GC 回收对象的引用类型,适用于缓存、事件监听管理等场景;需通过 Target 或 TryGetTarget 检查有效性,推荐使用泛型 WeakReference。

WeakReference 是 C# 中一种特殊的引用类型,它不阻止垃圾回收器(GC)回收其所指向的对象。换句话说,只要没有强引用指向该对象,即使存在 WeakReference,GC 仍可在下一次回收周期中将其回收。
为什么需要 WeakReference?
常用于缓存、事件监听器管理、大对象临时持有等场景,避免因引用导致对象长期驻留内存,造成内存泄漏或资源浪费。
- 比如缓存图像数据:用 WeakReference 持有,内存紧张时自动释放,下次需要时再重建
- 比如 UI 控件订阅事件后忘记取消:用弱引用持有订阅者,避免控件已销毁但事件源仍强引用它
如何创建和使用 WeakReference
创建后需通过 Target 属性访问对象,并始终检查是否为 null(已被回收):
var obj = new byte[1024 * 1024]; // 1MB 对象 WeakReference weakRef = new WeakReference(obj);obj = null; // 切断强引用 GC.Collect(); // 主动触发回收(仅调试用)
if (weakRef.Target is byte[] recovered) { Console.WriteLine("对象还在"); } else { Console.WriteLine("对象已被回收"); }
WeakReference — 泛型版本更安全
推荐使用泛型版 WeakReference,避免装箱/拆箱,类型安全,且提供 TryGetTarget(out T target) 方法,语义更清晰:
-
TryGetTarget返回bool表示是否成功获取,同时输出目标对象 - 无需类型转换,无运行时异常风险
- 性能略优,尤其对值类型或频繁访问场景
注意点和常见误区
WeakReference 不是“延迟回收开关”,它不控制 GC 行为,只被动反映对象存活状态:
- GC 是否回收取决于当前内存压力、代龄、根引用等,WeakReference 无法预测或干预
- 不要在多线程中直接多次访问
Target,应先用TryGetTarget获取一次并缓存结果 - 不能用于跨 AppDomain 或序列化场景(.NET Core/.NET 5+ 已无 AppDomain)
基本上就这些。WeakReference 本身不复杂,但容易忽略“对象随时可能消失”这一本质,正确使用的关键是:始终检查有效性、避免重复解引用、优先选泛型版本。








