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