When working with https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions[anonymous functions], it is important to keep in mind that each time you create one, it is a completely new instance.
In this example, even though the same lambda expression is used, the expressions are stored separately in the memory and are therefore not equal or the same.
This is even more true when working with https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/[events] since they are https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/how-to-combine-delegates-multicast-delegates[multicast delegates] that offer ways of https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events[subscribing and unsubscribing] to them. If an anonymous function is used to subscribe to an event, it is impossible to unsubscribe from it. This happens because to remove the entry from the subscription list, a reference to the original method is needed, but if the anonymous function has not been stored before subscribing, there is no way to find a reference to it.
Instead, store the callback to a variable or a named method and use the variable or method to subscribe and unsubscribe.
== How to fix it
Store the callback to a variable or a named method and use the variable or method to subscribe and unsubscribe.
=== Code examples
==== Noncompliant code example
[source,csharp,diff-id=1,diff-type=noncompliant]
----
event EventHandler myEvent;
void DoWork()
{
myEvent += (s, e) => Console.WriteLine($"Event raised with sender {s} and arguments {e}!");
// ...
myEvent -= (s, e) => Console.WriteLine($"Event raised with sender {s} and arguments {e}!"); // Noncompliant: this callback was never subscribed
}
----
==== Compliant solution
[source,csharp,diff-id=1,diff-type=compliant]
----
event EventHandler myEvent;
void LogEvent(object s, EventArgs e) => Console.WriteLine($"Event raised with sender {s} and arguments {e}!");
void DoWork()
{
myEvent += LogEvent;
// ...
myEvent -= LogEvent; // Compliant: LogEvent points to the same callback used for subscribing
}
----
== Resources
=== Documentation
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/[Events (C# Programming Guide)]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions[Lambda expressions and anonymous functions]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events[How to subscribe to and unsubscribe from events (C# Programming Guide)]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/how-to-combine-delegates-multicast-delegates[How to combine delegates (Multicast Delegates) (C# Programming Guide)]