Uladzimir Sharyi
Uladzimir Sharyi

Reputation: 154

Why does event unsubscribing work ("not leak") if using a lambda returned from a method?

There is simple class with event:

public class BaseEventProvider {
    public event EventHandler SomeEvent;

    public void Publish() {
        SomeEvent?.Invoke(this, null);
    }
}

I know, that it is a difficult to unsubscribe from event, if you handle an event using lambda function and in major cases it leads to memory leaks. For example:

BaseEventProvider eventProvider = new BaseEventProvider();
eventProvider.SomeEvent += (s, e) => {
     Console.WriteLine("was handled!");
};

But why in such case unsubscribing works:

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!"); 
        };
    }
}

Console output shows the event was only handled once:

was handled!

Is there something under the hood, probably after compilation and code optimization?

Upvotes: 1

Views: 86

Answers (1)

Andrius Naruševičius
Andrius Naruševičius

Reputation: 8578

Since each lambda expression returns a different heap of code, it has a different MethodInfo data which you can extract like in here. Thus these are two different addresses of the methods and your attempt to unsubscribe from lambda expression would do nothing since you would be providing a different "method". Meanwhile, unsubscribing from a method refers to the same MethodInfo (objects are equal) and will succeed in unsubscribing.

Upvotes: 2

Related Questions