如何通过Delete方法将HybridObject所有引用置空以实现GC回收?
核心需求:实现HybridObject.Delete方法自动清空所有强引用
我正在开发一款基础游戏引擎,需要实现HybridObject类的Delete方法:调用该方法时,所有指向当前HybridObject实例的强引用(如Application类的obj1/obj2属性、Test对象列表中的obj属性等)必须被置空,确保实例能被GC回收。仅清空单个引用无效,其他强引用会阻止GC工作。
已尝试的方案(均不可行)
- 反射遍历所有对象实例:复杂度极高,性能损耗严重,无法用于游戏引擎场景
- 在
HybridObject内添加Instance属性供外部引用:未实现自动清空所有引用的效果
示例代码
Application类代码
public class Application { HybridObject obj1; HybridObject obj2; List<Test> tests = new List<Test>(); public Application() { obj1 = new HybridObject(); obj2 = obj1; for (int i = 0; i < 1000; i++) { Test test = new Test(); test.obj = obj1; tests.Add(test); } obj1.Delete(); // 期望此调用将所有指向该HybridObject的引用置空 while (true) { CheckIfNull(); } } void CheckIfNull() { if (obj1 == null) Console.WriteLine("Destroyed 1"); if (obj2 == null) Console.WriteLine("Destroyed 2"); foreach (var t in tests) { if (t.obj == null) { Console.WriteLine("Destroyed From List"); } } } }
Test类代码
public class Test { public HybridObject obj; }
HybridObject类代码
public class HybridObject { public void Delete() { // 需实现:将所有指向当前HybridObject的引用置空 } }
简化场景
HybridObject obj = new HybridObject(); List<HybridObject> objects = new List<HybridObject>(); objects.Add(obj); objects.Add(obj); obj = null; // 期望此操作后列表中所有obj引用也变为null
高效可行的解决方案:引用包装类模式
核心思路是让所有外部代码不直接持有HybridObject的强引用,而是持有一个包装类的引用。当调用Delete时,仅需清空包装类内部的实例引用,所有外部包装类就会自动指向null,原实例失去所有强引用后即可被GC回收。
实现代码
新增HybridObjectRef包装类
public class HybridObjectRef { // 内部存储真实的HybridObject实例 public HybridObject Instance { get; private set; } public HybridObjectRef(HybridObject instance) { Instance = instance; } // 供HybridObject调用,清空内部实例引用 internal void ClearInstance() { Instance = null; } }
修改HybridObject类
public class HybridObject { private readonly HybridObjectRef _ref; public HybridObject() { // 实例化时自动创建对应的包装类 _ref = new HybridObjectRef(this); } // 对外暴露包装类引用 public HybridObjectRef Ref => _ref; public void Delete() { // 清空包装类内部的实例引用 _ref.ClearInstance(); } }
修改Application类(使用包装类引用)
public class Application { HybridObjectRef obj1Ref; HybridObjectRef obj2Ref; List<Test> tests = new List<Test>(); public Application() { HybridObject obj1 = new HybridObject(); // 持有包装类引用而非直接持有HybridObject obj1Ref = obj1.Ref; obj2Ref = obj1.Ref; for (int i = 0; i < 1000; i++) { Test test = new Test(); test.objRef = obj1.Ref; tests.Add(test); } obj1.Delete(); // 调用后所有包装类的Instance都会变为null while (true) { CheckIfNull(); } } void CheckIfNull() { // 通过包装类的Instance属性访问真实实例 if (obj1Ref.Instance == null) Console.WriteLine("Destroyed 1"); if (obj2Ref.Instance == null) Console.WriteLine("Destroyed 2"); foreach (var t in tests) { if (t.objRef.Instance == null) { Console.WriteLine("Destroyed From List"); } } } }
修改Test类(使用包装类引用)
public class Test { public HybridObjectRef objRef; }
简化场景修改后
HybridObject obj = new HybridObject(); List<HybridObjectRef> objects = new List<HybridObjectRef>(); objects.Add(obj.Ref); objects.Add(obj.Ref); obj.Delete(); // 调用后列表中所有Ref的Instance都会变为null
方案优势
- 性能优异:无需反射遍历,
Delete操作仅需修改包装类的内部引用,时间复杂度O(1),完全适配游戏引擎的性能要求 - 实现简单:仅需新增一个包装类,修改外部引用类型即可,无需大规模重构现有代码
- 逻辑可靠:所有外部引用通过包装类间接指向实例,调用
Delete后所有间接引用都会失效,原实例会被GC正常回收
内容的提问来源于stack exchange,提问作者LJH
相关产品推荐
相关产品推荐

