.net 将对对象的所有引用设置为空

beq87vna  于 2023-04-22  发布在  .NET
关注(0)|答案(1)|浏览(121)

我有这个示例代码是不完整的,因为我不知道如何做我想做的事情。

// This class will never be garbage collected
    // It is the core to my Game Engine Loop.
    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(); // This line should Null all properties using obj1 as a value.

            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");
                }
            }
        }
    }
public class Test
    {
        public HybridObject obj;
    }
public class HybridObject
    {
        public void Delete()
        {
            // SET ALL REFERENCES THAT POINT TO THIS HYBRIDOBJECT TO NULL
        }
    }

小示例

如果我们只是抽象掉我的代码的混乱。问题归结为这个,我如何在下面的例子中设置使用obj的所有内容为null?

HybridObject obj = new HybridObject();
List<HybridObject > objects = new List<HybridObject>();
objects.Add(obj);
objects.Add(obj);
obj = null; // If I set this all obj's in the list would be null as well.

说明

现在让我解释一下,我正在做一个基本的游戏引擎。
我尝试使用Delete方法将所有对我创建的HybridObject的引用设置为null。当我调用obj1.Delete()时,'Application' obj 1、obj 2属性和所有'Test' obj属性都需要设置为null,因为我将obj 1属性设置为新的HybridObject(),然后将所有其他属性值(如obj 2)设置为obj 1。
当我调用obj1.Delete();指向(obj 1)HybridObject的所有内容现在都应该变为null。然后HybridObject最终可以被垃圾收集,因为没有更多的引用。设置obj 1 = null;并不能解决这个问题,因为它不会将其他引用设置为null。
obj 1属性可以传递到任何地方,比如传递到另一个类属性,列表,结构体等。那么我如何处理将所有内容设置为null而不手动跟踪所有引用?HybridObject永远不会被销毁,因为仍然会有对它的强引用。
那么,如果在应用程序运行时,我创建了数百万个对象,但没有一个对象因为它们持有的强引用而被销毁,那会怎么样呢?如果我在应用程序'obj 1'中创建的一个HybridObject随着时间的推移被传递到数百万个其他地方,比如集合中,那会怎么样呢?(当然,这都是理论上的)
问题是,我如何删除所有指向一个对象的引用或指针,这样它就可以被垃圾回收了?我不确定这是否可能。

Things I have tried

1.我找到了一个使用反射的解决方案,但是当考虑到如何存储HybridObject(如属性、集合、结构等)时,它变得非常复杂,然后它必须在运行时运行我创建的每个对象示例。它不是很快,所以我不认为这是一个好主意。
1.尝试在HybridObject中创建一个对象Instance属性,然后使所有内容都引用该Instance属性,当我将Instance属性设置为null时,我希望指向该Instance属性的所有内容都反映该更改并变为null。但我无法使其工作。

drnojrws

drnojrws1#

我对使用Unity很满意,它允许这种行为
Unity是一个完全不同的运行时,其中null检查实际上并不是检查引用是否为null引用(即它指向“空存储器”)例如参见this answer,即1)它并不意味着对象占用的所有内存都可以被GCed(因此,所有的问题,你可以在“香草”C#,你试图避免)2)有可能得到truethis == nullsee this SO question),从“vanilla”C#的Angular 来看,这是没有多大意义的。
如果您只检查object!= null,则很容易避免这种情况。
如果你所要求的是可能的,那就不容易避免。特别是在多线程环境中。因此,如果任何引用可以在任何时候被无效,那么就没有办法保证在检查之后引用实际上不是null(除非使用一些魔法锁定,这可能会杀死所有性能并导致死锁)。
因此,总而言之,对于任何继承UnityEngine.Object与null比较的东西,并不意味着你认为它实际上意味着什么,所以你可以考虑以下选项:

  • 遵循Unity的模式-暴露的API类是内部资源的 Package 器,可以清除这些资源,并使用自定义==创建基类,这些基类将“伪造”空值。
  • 就我个人而言,我会考虑使用IDisposable模式(可能与通常的实现有一点不同-当在已处理对象上调用某些内容时不会抛出,而是使其成为no-op,但这是有争议的)
  • 设计一些API来为obj1.OnDelete注册一些回调,这样用户代码就可以执行必要的操作,尽管我认为它很快就会变得过于繁琐
  • 由于你需要依赖开发者在某个时候以某种方式清理(即发布对“ Package 器”的引用),也许完全依赖这一点是值得的,至少对于一些基本的游戏引擎来说。

阅读更多:

相关问题