Action< T>当所有其他对类实例的引用被删除时,防止封闭类实例被GCed

本文关键字:实例 删除 GCed 引用 其他 Action | 更新日期: 2023-09-27 18:13:04

我想知道Action<T>是否阻止了当所有其他对此类类实例的引用在运行时被删除时封闭类实例被垃圾收集?

public class Class1
{
    private Action<string> _callback;
    public Class1(Action<string> callback)
    {
        _callback = callback;
    }
    public void DoSomething(string msg)
    {
        _callback(msg);
    }
}
public class Class2
{
    private List<Class1> _class1s;
    public Class2()
    {
        _class1s = new List<Class1>();
    }
    public void AddClass1Instance()
    {
        _class1s.Add(new Class1(OnClass1DoSomething));
    }
    public void RemoveLastClass1Instance()
    {
        if(_class1s.Count > 0)
        {
            _class1s.RemoveAt(_class1s.Count - 1);
        }
    }
    private void OnClass1DoSomething(string msg)
    {
    }
}

在这个简单的例子中,当我在Class2中调用RemoveLastClass1Instance()时,Class1实例将被垃圾收集,还是通过Action<string>保留对OnClass1DoSomething()的引用?我的目标是完全删除Class1实例,并对它们进行垃圾收集。

编辑:(根据Jon Skeet的评论,我添加了以下代码以更好地理解

public class Class1
{
    public event Action<string> Event;
    public Class1()
    {
    }
    public void DoSomething(string msg)
    {
        var handle = Event;
        if (handle != null)
        {
            handle(msg);
        }
    }
}
public class Class2
{
    private List<Class1> _class1s;
    public Class2()
    {
        _class1s = new List<Class1>();
    }
    public void AddClass1Instance()
    {
        var newClass1Instance = new Class1();
        newClass1Instance.Event += OnClass1DoSomething;
        _class1s.Add(newClass1Instance);
    }
    public void RemoveLastClass1Instance()
    {
        if(_class1s.Count > 0)
        {
            _class1s.RemoveAt(_class1s.Count - 1);
        }
    }
    private void OnClass1DoSomething(string msg)
    {
    }
}

Action< T>当所有其他对类实例的引用被删除时,防止封闭类实例被GCed

我想知道Action<T>是否阻止封闭类实例被垃圾收集,当所有其他引用到这样的类实例在运行时被删除?

。如果委托实例仍然在其他地方被引用,并且它有一个Class1实例的目标,那么它将阻止Class1的实例被垃圾收集-但实际上,Action<string>的目标是Class2的实例。

基本上,当涉及到垃圾收集时,委托没有什么神奇之处。如果委托引用实例方法,则该实例的目标被保存为引用…如果委派仍然是可达的,委派的目标仍然是可达的。在您的例子中,委托本身是不可访问的,并且您显然不担心Class2实例是否可以被垃圾收集。

使用事件的改变根本不影响这一点-它仍然是Class1的实例有一个引用(通过委托)到Class2的原始实例…从Class2Class1实例的only引用是通过列表。