2

I'm rather new to these could someone explain the significance (of the following code) or perhaps give a link to some useful information on lambda expressions? I encounter the following code in a test and I am wondering why someone would do this:

foo.MyEvent += (o, e) => { fCount++; Console.WriteLine(fCount); };

foo.MyEvent -= (o, e) => { fCount++; Console.WriteLine(fCount); };

My instinct tells me it is something simple and not a mistake, but I don't know enough about these expressions to understand why this is being done.

Andras Vass
  • 11,478
  • 1
  • 37
  • 49
Matt
  • 303
  • 1
  • 2
  • 6
  • 2
    This code will not work as expected. – SLaks Mar 12 '10 at 20:14
  • 2
    This is a duplicate of http://stackoverflow.com/questions/2333560/lamda-explanation-and-what-it-is-as-well-as-a-good-example and many others. I'd vote to close, but am out of votes for the day. – John Saunders Mar 12 '10 at 20:19
  • 1
    John: It may be a duplicate, but not of 2333560. – Gabe Mar 12 '10 at 20:21
  • John, I don't think it's a duplicate (at least not of 2333560). I don't think he's just asking "what is a lambda?" He's asking "what is the significance of adding and removing the same lambda from an event?" -- which, as SLaks observes, is not what the author of the code expected! – itowlson Mar 12 '10 at 20:23
  • Or, given that he's accepted the "what is a lambda" answer, I could be completely wrong... – itowlson Mar 12 '10 at 20:24

6 Answers6

10

The lambda expression (o, e) => { fCount++; Console.WriteLine(fCount); } is interpreted as an anonymous method that takes two arguments o, e (whose types are inferred from the delegate type used for MyEvent and returns void. It captures the fCount variable in the body of the enclosing method (if it's a local variable). The += operator will subscribe the anonymous method to the event and the -= unsubscribes a delegate from an event.


Update (re: concerns about delegate instance equality):

It's important to know that it's not a good idea to try to unsubscribe from the event like that. The language specification, permits, but doesn't require that the delegate in the second line to be equal to the delegate from the first line. That is, the compiler is allowed to treat the two anonymous function bodies as if it was the same function or if it wasn't (because the anonymous function body is semantically identical and the set of captured variables is equal too). Even if it works as expected in your compiler, it might break in the next version. To quote the C# Language Specification on that:

C# Language Specification (Section 7.9.8 Delegate equality operators):

Invocation list entries produced from evaluation of semantically identical anonymous-function-expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

If the compiler treats the two anonymous function expressions as equal, the second line will unsubscribe the previous anonymous method from the event. If it doesn't the second line will not do anything special (it's not an error to unsubscribe a delegate from an event invocation list if it doesn't already exist in the list).

Community
  • 1
  • 1
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • I think his concern may be with the `-=` side of things, i.e. what is the effect of *removing* the anonymous method from the event? (My understanding is that this *is* a mistake -- .NET will not magically work out that the removed anonymous method is the same as the previously added one, so the event handler will remain hooked up.) – itowlson Mar 12 '10 at 20:20
  • @itowlson: Clarified the answer to address that issue. – Mehrdad Afshari Mar 12 '10 at 20:31
2

Here is a great video about lambda expressions in C#. The video is 2 years old, but it gets users up to speed on the functionality that was relatively new at that time. The content you're interested begins around 3:02.

Software.Developer
  • 991
  • 10
  • 16
1

It is a mistake. It's adding an anonymous delegate to the MyEvent event, but trying to remove a different instance of the same anonymous delegate. Since the instance is probably always different, it may never actually remove the original delegate, which is almost certainly not what you want.

Gabe
  • 84,912
  • 12
  • 139
  • 238
0

It is an implementation of an event handler using a lambda expression. The advantag is that it is a) inline, i.e. no additional function declaration is required and b) that it can draw on the variables declared in the function where you found this declaration (using closures).

AxelEckenberger
  • 16,628
  • 3
  • 48
  • 70
0

It looks like he's thinking that's equivalent to:

var eh = new EventHandler(delegate(object o, EventArgs e)
    { fCount++; Console.WriteLine(fCount); };

foo.MyEvent += eh;

foo.MyEvent -= eh;

But the unregistering isn't going to work as expected since it has no way of knowing its supposed to be referring to the registered delegate.

The syntax he's using for adding the handler is just a shorter way of attaching an anonymous delegate to an event and is pretty popular syntax, but not something I'd recommend using if you also have to unregister it.

heisenberg
  • 9,665
  • 1
  • 30
  • 38
0

Lambda expressions are a syntactic shorthand to declare a function. So,

(o, e) => { fCount++; Console.WriteLine(fCount); }

means a function that takes two arguments and executes two statements.

As for the code snippet, the unsubscribe '-=' will not work because it is shorthand for:

foo.MyEvent += new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent -= new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );

This is actually a resource leak. Instead store a reference to the handler and use that to perform the subscribe and unsubscribe:

var handler = new EventHandler( (o, e) => { fCount++; Console.WriteLine(fCount); } );
foo.MyEvent += handler;
foo.MyEvent -= handler;
Phillip Ngan
  • 15,482
  • 8
  • 63
  • 79