Click here to Skip to main content
15,888,984 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I have seen the following code example online:

C#
framesReplay.FrameReady += frame => synchronizationContext.Send(state => AllFramesReady.Raise(new ReplayAllFramesReadyEventArgs { AllFrames = frame }), null);


This is attaching an event in code within the same method rather than having another method dedicated for handling the event such as:

C#
        framesReplay.FrameReady += eventHandlerMethod;

private void eventHandlerMethod(EvantArgs args)
{

            synchronizationContext.Send(state => AllFramesReady.Raise(new ReplayAllFramesReadyEventArgs { AllFrames = frame }), null);
}


How do I therefore detach the handler? Normal way of:

C#
framesReplay.FrameReady -= eventHandlerMethod;


Thanks!
Posted
Updated 13-Nov-13 5:13am
v2
Comments
Sergey Alexandrovich Kryukov 13-Nov-13 12:20pm    
One simply question is: why would you detach it? I usually design the code the way it is never needed. And I don't allow any memory leaks possible due to not removing handler. The event instance is removed by removing the object of the event declaring type. Can you see the point?
—SA

When you define an Event Handler using Lambda notation, the resulting method is "anonymous" in the sense it's not available to be manipulated by the programmer once it has been created unless you keep a reference to it. That's really the same "visibility" logic that applies to anything you create within the scope of a some method, class, etc.

And, of course, you can maintain a reference to an Event Handler created "inline;" a reference you can, at any time, remove in the standard way you remove an Event Handler from a Multicast Delegate.

Assume you have two Button Controls on a WinForm, button1, button2: consider the following code:
// EventHandler variable definitions
EventHandler Button1Click;
MouseEventHandler Button2MouseDown;

// boolean used to toggle connected/removed state of EventHandlers 
private bool AreEventsWired = false;

private void button1_Click(object sender, EventArgs e)
{
    AreEventsWired = ! AreEventsWired ;

    if (AreEventsWired )
    {
        // use Lambda notation to create a Click EventHandler [1]
        Button1Click = (object obj, ea) => { MessageBox.Show("Button1 Click"); };
        // wire-up the EventHandler to the Click Event Delegate of the Button
        button1.Click += Button1Click;

        // note for MouseDown we need a MouseEventArgs argument [2]
        Button2MouseDown = (object obj, MouseEventArgs ea) => { MessageBox.Show("Button2 MouseDown"); };
        button2.MouseDown += Button2MouseDown;
    }
    else
    {
        // remove the EventHandlers
        button1.Click -= Button1Click;
        button2.MouseDown -= Button2MouseDown;
    }
}
Can you predict what will happen, or not happen, the first and second time, you click on button1 at run-time ?

[1] note that here we do not specify the parameter Types in our Lambda form EventHandler declaration: the compiler assumes that we are using the default Types, Object, and EventArgs.

[2] note that here the compiler requires we specify both Types, Object, and MouseEventArgs because MouseEventArgs is not the default EventHandler event-argument Type.

Discussion: if you really think about it you'll see that all we have really done in the above example is just use a fancy way to create a defined EventHandler. Its usage will be exactly the same as if you had created a named EventHandler in a separate method.

So, when your code does require you keep a reference to an EventHandler, unless you are really thrilled by the act of writing Lambda notation: you might well ask yourself if there's any advantage to writing code this way.

Further Out: if C# gave us direct access programmatically to the "guts" of MultiCast Delegates, so we could dynamically inspect which EventHandlers were wired-up, and mess around with them: well, that would be another language ?
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 13-Nov-13 13:30pm    
Good points, a 5. A name or a reference — same thing in this respect. A handler method name can be considered as a reference to some delegate instance (not exactly though).
—SA
It's not possible. Not in the way you describe it. In your code you declared an anonymous delegate - it has no name, so you can't remove it...

First of all consider SA's comment - you can remove the need for detach by good code design.

Second, you do not gain nothing with the anonymous delegate, because the compiler will wrap it up as a method you used to declare. So if it's for nicer code, but you also must do the detach thing, you must give in...
 
Share this answer
 
Comments
mccaber82 13-Nov-13 12:59pm    
Thanks for the feedback guys!
Sergey Alexandrovich Kryukov 13-Nov-13 13:11pm    
Sure. I voted 4 because "gain nothing with the anonymous delegate" is not quite correct. You can gain code which is better for maintenance, look more elegant, etc. Importantly, you can also use the closure feature, with the benefit of better encapsulation. Of course, if the feature is used in a wise well-designed ways.

By the way, look at Solution 2.
—SA
Kornfeld Eliyahu Peter 13-Nov-13 16:24pm    
I agree, I should be more precise and write 'gain nothing in performance'...
About solution 2 - I'm not sure what the difference between variable holding reference to delegate and between a method that acts as delegate - in means of maintenance, but for sure it's a good solution. mcab21 can start and build of his own coding style...
Sergey Alexandrovich Kryukov 13-Nov-13 16:49pm    
The difference is big and very non-trivial. The usual MSDN documentation is wildly insufficient. I explained some of it in my article, a section "4.1. On the Nature of Delegate Instance":
Dynamic Method Dispatcher. Please see, I think it's pretty interesting...
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900