C# 将对对象的所有引用设为null,以便可以收集该对象

C# 将对对象的所有引用设为null,以便可以收集该对象,c#,C#,我正在尝试实现类似Unity3D中的GameObject的行为 在任何给定的应用程序中,我有很多很多对象,它们引用任何给定数量的其他对象。每个对象都可以标记为删除,并在删除时进行标记;我需要知道如何取消对它的任何引用,以便它可以被GC收集并从范围中完全删除。我不是在寻找一种伪造的方法,就是在寻找一种实际的方法 出于所有意图和目的;如果一个对象引用另一个对象,并且被引用的对象被销毁,我需要该引用显示为null。如果我做不到这一点,那么我唯一的其他选择就是每次使用它们时检查每个引用,并手动评估它是否

我正在尝试实现类似Unity3D中的
GameObject
的行为

在任何给定的应用程序中,我有很多很多对象,它们引用任何给定数量的其他对象。每个对象都可以标记为删除,并在删除时进行标记;我需要知道如何取消对它的任何引用,以便它可以被GC收集并从范围中完全删除。我不是在寻找一种伪造的方法,就是在寻找一种实际的方法


出于所有意图和目的;如果一个对象引用另一个对象,并且被引用的对象被销毁,我需要该引用显示为null。如果我做不到这一点,那么我唯一的其他选择就是每次使用它们时检查每个引用,并手动评估它是否已被销毁,这是不实际的。

您不能将
(也称为“您自己”)设置为
null
,这样对您的引用将丢失/销毁<代码>此为只读


您可以使用事件告诉引用实例的人将其设置为
null
。在将实例设置为
null

时,不要忘记取消订阅事件处理程序。我知道有两种方法与您描述的方法非常接近:

方法1:WeakReference 仅使用
WeakReference
引用对象,保留硬引用的“
DataManager
”除外

然后,您可以通过清除
DataManager
的硬引用来“标记”垃圾收集实例

public class DataManager
{
    private readonly HashSet<object> data = new HashSet<object>();


    public void RegisterInstance(object instance)
    {
        data.Add(instance);
    }

    public void FreeInstance(object instance)
    {
        data.Remove(instance)
    }
}


public class Foo
{
    List<WeakReference<Bar>> bars = new List<WeakReference<Bar>>();

    private readonly DataManager dataManager;


    public Foo(DataManager dataManager)
    {
        this.dataManager = dataManager;
    }

    public void LogSomething()
    {
        bars.Add( Bar.Create(dataManager, 3, "Susan"));
        bars.Add( Bar.Create(dataManager, 4, "Bob"));
        bars.Add( Bar.Create(dataManager, 0, "Megan"));

        dataManager.FreeInstance(bars[1]);
        CG.Collect();

        for(int i = bars.Count - 1; i >= 0; i--;)
        {
            // hard reference to not loose the reference target between now and logging
            Bar bar;
            if(!bars[i].TryGetTarget(out bar)
            {
                bars.RemoveAt(i);
                continue;
            }

            Debug.Log($"{bar.value.Data2} has {bar.value.Data1} chocolate bars");
        }
    }
}


public class Bar
{
    public int Data1 { get; private set; }
    public string Data2 { get; private set; }

    private Bar(int data1, string data2)
    {
        Data1 = data1;
        Data2 = data2;
    }

    public static WeakReference<Bar> Create(DataManager dataManager, int data1, string data2)
    {
        var bar = new Bar(data1, data2);
        dataManager.RegisterInstance(bar);
        return new WeakReference(bar);
    }
}
您还可以覆盖
Wrapper
equals
方法,以实现以下行为:

var bar = new Wrapper<Bar>(null);
var isWrappedValueNull = bar == null;
// overwrite 'equals' if you want isWrappedValueNull to be true in this case
var bar=新包装(空);
var isWrappedValueNull=bar==null;
//如果希望在本例中isWrappedValueNull为true,请覆盖“equals”

我是用android应用程序写的-示例代码可能有一些小错误

@user2312610:很抱歉,但我很确定这在.NET中是不可能的。你能举一个更详细的例子吗?@user2312610那些拥有多年.net经验的人很高兴地告诉你,你误解了你在unity中看到的东西。这是不可能的。你的意思是?是的,确实。根据语言规范,后者是不可能的。@user2312610:是的,如果只引用外部实例,而不引用内部实例,这会有所帮助。
var bar = new Wrapper<Bar>(null);
var isWrappedValueNull = bar == null;
// overwrite 'equals' if you want isWrappedValueNull to be true in this case