views:

266

answers:

4

I am confused by the syntax for removing event handlers in C#.

Something += new MyHandler(HandleSomething); // add
Something -= new MyHandler(HandleSomething); // remove

The "new" creates a new object on each line, so you add one object and then ask it to remove a different object.

What is really going on under the covers that this can work?
It sure isn't obvious from the syntax.

A: 

YOu need to retain the reference to the handler that was added...

var myHandler = new MyHandler(handlesomething);
Something += myHandler;
Something -= myHandler;

using "new" creates a new handler and you end up asking to remove a handler that was never added.

It's just like adding a delegate to a list of delegates and then saying .Remove(someDelegate);

DataDink
Did you really mean to leave in the "new" on the bottom two code lines? This syntax is even more confusing. I have seen the original syntax recommended... is it wrong?
Mark T
This is incorrect. If you do Something -= new Handler() it WILL remove the handler that was added.
BFree
No I didn't, but in the .5 seconds it took me to go back in and edit it I had already been down-voted twice. lol
DataDink
A: 

You can think of events as placeholder methods for the delegated logic that executes when the event is raised. A single event can have multiple subscribers (multi-casting), so the += and -= syntax is how a single event handler is attached or removed. Simply doing assignment would reset the event's subscriptions, which could cause unwanted side-effects.

EDIT: this link explains more about eventing in C#

Josh E
reason for the downvote please?
Josh E
Why the down vote? This seems like a perfectly valid response.
Paul Sasik
Restating the OP's question: "Why we can += one new'ed object and -= an entirely different new'ed object and get the desired effect?" Josh E doesn't answer *why* we can attach 'a' and remove 'b' where 'a' and 'b' are different instances and still get what we want.
JeffH
I had thought that by talking about subscription I covered that. Charles Bretana's answer covers this well so I'll refrain from editing my response
Josh E
+15  A: 

The += and the -= are syntax shortcuts for built-in internal methods named Add(), and Remove(), which add or remove a pointer to an internal linked list of delegates that the delegate has as a private field. When you run Remove, it starts at the head of the linked list and examines each delegate in the list one at a time until it finds one that is "equal" to the one you passed to the Remove() method. ( using -= syntax)

Then, it removes that one from the linked list, and patches the linked list to retain it's connectivity...

In this context, the 'equals' method (for a delegate()) is overridden so that it only compares the target of the delegate, and the methodPtr, which will be the same even though you have created a new delegate to pass to Remove...

Charles Bretana
+3  A: 

The "new MyHandler" is actually redundant. You can simply do

Something += HandleSomething; // add
Something -= HandleSomething; // remove

All events in C# are multicast delegates, so the += and -= syntax indicates that you are adding/removing a delegate to the list of delegates that will be called.

As for what's going on behind the scenes, the best explanation that I've found is Jon Skeet's.

womp
That's actually the same as the provided example, though the newer C# adds that for you.
Dykam
You can leave the new'ing out, but if you let Visual Studio fill it in for you by typing: "Something +=" then <tab>, the autogenerated code will complete it similar to this: "Something +=new MyHandler(HandleSomething);" The OP is asking what goes on under the hood so that the new'ing way works.
JeffH
womp
Although this syntax shortcut does the same thing as the original syntax shortcut, at least this one makes good sense. This can be used without causing confusion. I like this new syntax much better.
Mark T