C# 强引用和弱引用的区别 弱引用的使用

本文深入探讨了强引用和弱引用的概念,解释了它们如何影响对象的引用计数及垃圾回收机制。强引用直接关联对象,增加其引用计数;而弱引用保持对象链接,却不增加引用次数,便于垃圾回收器适时清理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是强引用?
Object obj = new Object(); 这就是一个强引用,内存分配一份空间用以存储Object数据。当一个对象被强引用的形式创建的时候,本身引用的次数为1.
接着Object o = obj.执行之后Object的引用次数为2.所以强引用会导致被引用的对象的引用次数加1.
什么是弱引用?
弱引用可以保持该对象的引用,但是不增加对象的引用次数。这样GC就能在必要时候释放对象,回收内存。
对于那些创建便宜但耗费大量内存的对象,希望保持该对象的引用,又要在应用程序中使用,同时希望GC回收,可以考虑使用弱引用。
弱引用分为短弱引用和长弱引用,默认使用的是短弱引用。
Short Weak Reference(短弱引用):一旦对象被垃圾回收,引用就会设置为null,上文所举的例子都是短弱引用。
Long Weak Reference(长弱引用):如果对象存在一个finalizer(终结器/析构函数) 并且引用被以正确的方式创建。那么引用将一直指向对象,直到finalizer结束。
使用时机:

对象相对较大,易于创建,生命周期高度可变。

使用方法:

public void ST()
{
    List<int> t = new List<int>(){1, 2, 3};
    StartCoroutine(Func(t));
}
public IEnumerator Func(List<int> t)
{
    WeakReference<List<int>> tweak = new WeakReference<List<int>>(new List<int>(t));

    yield return new WaitForSeconds(0.1f);
    
    if (tweak.TryGetTarget(out var list))
    {
        UnityEngine.Debug.Log("this is not null");
    }
    else
    {
        UnityEngine.Debug.Log("this is null");
    }
}

使用弱引用,结果this is null.
如果使用强引用,局部变量t在函数结束的时候还存在强引用,协程中还能获取到数组。

<think>嗯,用户问的是强引用弱引用是什么意思。之前他们问过C#如何避免内存泄漏,特别是WeakReference的使用场景,现在应该是在深入理解这个概念。首先,我需要回忆一下强引用弱引用的基本定义,然后想想怎么用简单的中文解释清楚。 强引用应该就是普通的对象引用,只要存在强引用,垃圾回收器就不会回收那个对象。比如用户之前提到的例子,比如事件未注销或者静态集合持有对象,导致对象无法被回收,这就是强引用导致的内存泄漏问题。 弱引用的话,像是WeakReference,允许引用对象,但不会阻止垃圾回收。当内存不足时,即使有弱引用,对象还是会被回收。这时候需要检查弱引用是否还存活,如果被回收了,就需要重新创建或者处理。用户之前提到的缓存系统事件监听都是典型的使用场景。 用户可能现在想更基础的理解这两个概念,而不仅仅是使用场景。可能需要举一些日常生活中的例子,比如强引用像是牢牢抓住一个东西,而弱引用像是用绳子轻轻系着,东西还在的时候可以用,但一旦需要,绳子会自动松开。 另外,需要区分短弱引用弱引用,可能用户没有提到,但作为补充说明可以让回答更全面。同时,可能要注意到WeakReference<T>普通WeakReference的区别,之前回答中也有提到泛型版本更安全。 还要注意用户可能对垃圾回收机制不太了解,需要简单解释一下GC如何根据引用来判断对象是否存活。比如,强引用会增加对象的引用计数,而弱引用不会,这样当只有弱引用存在时,对象就会被回收。 可能需要检查之前的回答是否有遗漏点,比如强引用弱引用的定义对比,使用时的注意事项,比如性能问题,或者如何正确使用弱引用避免空引用异常。 最后,结构上应该先定义强引用,再弱引用,对比两者的区别,应用场景,以及注意事项。确保用户能一步步理解,从基本概念到实际应用,再到注意点,结构清晰。</think>### 强引用弱引用的核心区别 #### 一、强引用(Strong Reference) **定义**: 普通对象引用,只要存在强引用指向对象,垃圾回收器(GC)**永远不会回收该对象**,即使内存不足时也优先触发内存扩容而非回收。 **代码示例**: ```csharp // 强引用示例 var obj = new MyClass(); // obj是强引用 List<MyClass> cache = new List<MyClass> { obj }; // cache仍持有强引用 → obj永远不会被回收 ``` **特点**: - **内存安全性**:对象生命周期完全可控 - **风险**:过度使用会导致内存泄漏(如忘记移除引用) **典型场景**: - 核心业务对象 - 需要长期驻留内存的数据 --- #### 二、弱引用(Weak Reference) **定义**: 特殊引用类型,允许访问对象但**不阻止GC回收**。当内存不足时,GC会回收仅被弱引用指向的对象。 **代码示例**: ```csharp // 弱引用示例 var obj = new MyClass(); WeakReference<MyClass> weakRef = new WeakReference<MyClass>(obj); obj = null; // 移除强引用 GC.Collect(); // 触发垃圾回收 if (weakRef.TryGetTarget(out MyClass target)) { // 对象未被回收时可访问 } else { // 对象已被回收 → 需要重建 } ``` **特点**: - **内存友好性**:自动释放非关键资源 - **不确定性**:对象可能随时被回收,访问前必须检查有效性 --- ### 三、对比表 | 特性 | 强引用 | 弱引用 | |---------------------|--------------------------------|--------------------------------| | **GC回收影响** | 阻止回收 | 不阻止回收 | | **内存泄漏风险** | 高(需手动管理) | 低(自动释放) | | **访问可靠性** | 始终有效 | 需检查有效性 | | **典型用途** | 核心数据、长期持有对象 | 缓存、监听器、辅助数据 | --- ### 四、弱引用高级类型 1. **短弱引用(Short Weak Reference)** ```csharp new WeakReference(obj, trackResurrection: false); ``` - 对象被回收后立即失效(**常用类型**) 2. **长弱引用(Long Weak Reference)** ```csharp new WeakReference(obj, trackResurrection: true); ``` - 允许追踪对象复活(`Finalize`方法执行后仍可访问) --- ### 五、实战注意事项 1. **不要依赖弱引用存储关键数据** ```csharp // 错误用法:可能随时丢失数据 WeakReference<Config> configRef = new WeakReference(LoadConfig()); // 正确用法:关键数据使用强引用+弱引用双保险 Config _configStrongRef; // 强引用保底 WeakReference<Config> _configWeakRef; ``` 2. **高频访问场景需谨慎** ```csharp // 每次访问都检查弱引用 → 性能损耗 if (weakRef.TryGetTarget(out var obj)) { obj.Process(); } // 解决方案:临时转换为强引用 if (weakRef.TryGetTarget(out var tempObj)) { var strongRef = tempObj; // 创建局部强引用 strongRef.Process(); strongRef.AnotherOperation(); } ``` 3. **与ConditionalWeakTable配合** ```csharp // 键值均为弱引用的高级结构 var weakTable = new ConditionalWeakTable<Key, Value>(); weakTable.Add(key, value); // key被回收时自动移除对应条目 ``` --- ### 六、比喻理解 - **强引用** → 用铁链锁住物品:只要铁链存在,物品永远留在房间 - **弱引用** → 用纸条标记物品位置:当房间需要腾空间时,纸条标记的物品会被优先清理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值