You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:43:13