GC什么时候可以收集挂钩到事件的Lambda?

Mar*_*tze 5 .net c# lambda garbage-collection

如果我将Lambda挂钩到这样的事件:

static void DoSomething(Control control)
{
    control.SomeEvent += StaticMethodThatHandlesEvent;
    Control parentControl = control.Parent;
    parentControl.Disposed += (sender, args) =>
        {
            control.SomeEvent -= StaticMethodThatHandlesEvent;
        };
}
Run Code Online (Sandbox Code Playgroud)

在什么条件下可以收集lambda?如果收集了parentControl,它会被收集吗?可以收集parentControl(假设它已被正确处理,我的代码中没有任何引用)?

编辑:整个代码在静态类中.这有关系吗?

Evk*_*Evk 1

当您有这样的问题时,请尝试在不使用匿名方法的情况下执行此操作,并查看它需要什么才能工作:

internal class Program {
    private static void Main(string[] args) {
        DoSomething(new Control() {Parent = new Control()});
    }

    private static void DoSomething(Control control) {
        control.SomeEvent += MethodThatHandlesEvent;
        Control parentControl = control.Parent;
        parentControl.Disposed += new LambdaClass(control).OnDisposed;
    }

    private class LambdaClass {
        private readonly Control _control;
        public LambdaClass(Control control) {
            _control = control;
        }

        public void OnDisposed(object sender, EventArgs e) {
            // if MethodThatHandlerEvent is not static, you also need to pass and store reference to the wrapping class
            _control.SomeEvent -= MethodThatHandlesEvent;
        }
    }


    private static void MethodThatHandlesEvent(object sender, EventArgs e) {

    }

    private class Control {
        public event EventHandler SomeEvent;
        public event EventHandler Disposed;
        public Control Parent { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你有同样的情况,但没有任何匿名方法。问你的问题 - 控件和parentControl 已经相互引用,因此从parentControl 添加一个间接引用到控件(通过LambdaClass)不会改变情况。当没有其他从根(本地变量、静态变量等)引用它们时,parentControl 和 control(以及 LambdaClass 的实例)都应该由 GC 收集。.NET GC 收集循环引用没有问题。