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
EventHandler
instead 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