I was wiring up an event to use a lambda which needed to remove itself after triggering. I couldn't do it by inlining the lambda to the += event (no accessable variable to use to remove the event) so i set up an Action<object, EventArgs> variable and moved the lambda there. The main error was that it could not convert an Action<object, EventArgs> to an EventHandler. I thought lambda expressions were implicitly convertable to event handlers, why doesn't this work?
            Asked
            
        
        
            Active
            
        
            Viewed 1.4k times
        
    37
            
            
        
        ToolmakerSteve
        
- 18,547
 - 14
 - 94
 - 196
 
        RCIX
        
- 38,647
 - 50
 - 150
 - 207
 
5 Answers
51
            
            
        Action<Object, EventArgs> a = (o, ea) => { };
EventHandler e = a.Invoke;
        QrystaL
        
- 4,886
 - 2
 - 24
 - 28
 
- 
                    1This should be the answer. Nice! – Luke Vo Apr 04 '20 at 13:03
 
45
            Lambdas are implicitly convertible to delegate types with the right shape, but two same-shaped delegate types are not implicitly convertible to one another. Just make the local variable have type EventHandler instead.
EventHandler h = (o, ea) => { ... };
e += h;
...
e -= h;
(in case it helps:
Action<object, EventArgs> a = (o, ea) => { }; 
EventHandler e = a;  // not allowed
EventHandler e2 = (o,ea) => a(o,ea);  // ok
)
        Brian
        
- 117,631
 - 17
 - 236
 - 300
 
- 
                    2Except that e2 now goes through two function calls to actually do anything... eww. – Matthew Scharley Oct 11 '09 at 22:47
 - 
                    3I'm not promoting e2 as a good way to write code, I'm just using it as an example to demonstrate what is and is not legal with regards to the C# type system. – Brian Oct 11 '09 at 23:06
 - 
                    1
 - 
                    5It strikes me as a bit silly that you can't cast from one delegate type to another that is equivalent. Is there any good reason for this? – snarf Oct 12 '09 at 00:58
 - 
                    @Snarfblam: I'm guessing it's the covariance issue, as delegates are generics. I wonder if this issue has gone in .NET 4. – Cameron MacFarland Oct 12 '09 at 09:40
 - 
                    @Cameron - it has not. The new 4.0 covariance translates between `Func
` and `Func – Daniel Earwicker Oct 14 '09 at 09:36 - 
                    1On whether there is much value in using custom delegate types for events, see http://stackoverflow.com/questions/1120506/what-would-i-lose-by-abandoning-the-standard-eventhandler-pattern-in-net – Daniel Earwicker Oct 14 '09 at 09:39
 - 
                    @MatthewScharley - OTOH, the traditional `handler += myMethod` actually compiles into `handler += new EventHandler(myMethod)` - so the overhead is perhaps not that different. – ToolmakerSteve Jan 06 '20 at 20:01
 
3
            
            
        Declare your event as
public event Action<object, EventArgs> e;
Then you can directly add your action:
Action<object, EventArgs> a = something;
e += a;
        olaf
        
- 531
 - 4
 - 4
 
2
            
            
        In general, delegates can't be cast because they have no inheritance tree defining which casts are valid. To that end, you have two choices:
- Use a variable of type 
EventHandlerinstead of theAction<T1, T2> Use an inline declaration.
// option 1: local variable EventHandler eh = (o, ea) => { /* [snip] */ }; obj.event += eh; obj.event -= eh; // option 2: inline declaration obj.event += (o, ea) => { /* [snip] */ };
        Matthew Scharley
        
- 127,823
 - 52
 - 194
 - 222
 
- 
                    The whole point of using a variable was so that i could remove the event from the event handler while still inside the event. Still, +1. – RCIX Oct 11 '09 at 22:36
 
-1
            
            
        You can use an anonymous method instead:
Event += (sender, e) =>
{
     // Multiple lines
     // of code here
};
- 
                    2That's the whole point.... I have one set up only stored into a variable to i can have the event remove itself when fired, only it won't work. – RCIX Oct 11 '09 at 22:29