猿问

如果使用从方法返回的 lambda,为什么取消订阅事件(“不泄漏”)会起作用?

有一个带有事件的简单类:


public class BaseEventProvider {

    public event EventHandler SomeEvent;


    public void Publish() {

        SomeEvent?.Invoke(this, null);

    }

}

我知道,如果您使用 lambda 函数处理事件,并且在主要情况下会导致内存泄漏,则很难取消订阅事件。例如:


BaseEventProvider eventProvider = new BaseEventProvider();

eventProvider.SomeEvent += (s, e) => {

     Console.WriteLine("was handled!");

};

但是为什么在这种情况下取消订阅有效:


class Program {

    static void Main(string[] args) {

        BaseEventProvider eventProvider = new BaseEventProvider();

        eventProvider.SomeEvent += Handler();

        eventProvider.Publish();


        eventProvider.SomeEvent -= Handler();

        eventProvider.Publish();


        Console.ReadKey();

    }


    private static EventHandler Handler() {

        return (s, e) => {

            Console.WriteLine("was handled!"); 

        };

    }

}

控制台输出显示事件只处理一次:


was handled!

可能在编译和代码优化之后有什么秘密吗?


交互式爱情
浏览 177回答 1
1回答

郎朗坤

由于每个 lambda 表达式返回不同的代码堆,它具有不同的MethodInfo数据,您可以像这里一样提取这些数据。因此,这是方法的两个不同地址,您尝试取消订阅 lambda 表达式将无济于事,因为您将提供不同的“方法”。同时,取消订阅一个方法是指相同的MethodInfo(对象是平等的)并且会成功取消订阅。
随时随地看视频慕课网APP
我要回答