Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass an event as a parameter to a method [duplicate]

Tags:

c#

events

Possible Duplicate:
How to pass an event to a method?

Is it possible to pass an event as a parameter to a method?

For example, the following method subscribes to the event, does work, and unsubscribes from the event:

void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(         IEnumerable<TElement> elements,         ??? elementEvent)     where TEventArgs: EventArgs {     EventHandler<TEventArgs> handler = (sender, e) => { /* Handle an event */ };      foreach (var element in elements)     {          // Subscribe somehow          element.elementEvent += handler     }      // Do things      foreach (var element in elements)     {          // Unsubscribe somehow          element.elementEvent -= handler     } } 

Client code:

var elements = new [] { new Button(), new Button() }; SubscribeDoAndUnsubscribe(elements, ??? /* e => e.Click */); 

If it's not possible, how do I achieve the similar logic in other ways? Shall I pass pair of delegates for subscribe/unsubscribe methods?

like image 633
altso Avatar asked Dec 06 '11 22:12

altso


People also ask

How to pass variable as reference in c#?

To pass a value by reference, begin by initializing a variable and setting its value. Now, declare a method in the following syntax: Name(ref var). Inside the brackets is the value type parameter. Both of these must be placed into the static void Main() method of the object class.

Is it possible to pass an additional parameter to an event handler?

Parameters of the even handlers are defined by the "event arguments" class (derived from System. EventArgs ); and you cannot change the signature of the event handler. So, you should have asked, "can I pass additional information?". Of course you can.

How do you pass an event as a parameter?

To pass an event and parameter onClick in React:Pass an inline function to the onClick prop of the element. The function should take the event object and call handleClick . Pass the event and parameter to handleClick .


2 Answers

You have in fact discovered that events are not "first class" in C#; you cannot pass around an event as data. You can pass around a delegate to a method associated with a receiver as a first-class object by making a delegate. You can pass around a reference to any variable as a (mostly) first-class object. (I say "mostly" because references to variables cannot be stored in fields, stored in arrays, and so on; they are highly restricted compared to other kinds of data.) You can pass around a type by obtaining its Type object and passing that around.

But there is no way to directly pass around as data an event, property, indexer, constructor or destructor associated with a particular instance. The best you can do is to make a delegate (or pair of delegates) out of a lambda, as you suggest. Or, obtain the reflection object associated with the event and pass that around, along with the instance.

like image 55
Eric Lippert Avatar answered Sep 24 '22 05:09

Eric Lippert


No, unfortunately not.

If you look at Reactive Extensions, that suffers from a similar problem. Three options they use (IIRC - it's been a while since I've looked):

  • Pass in the corresponding EventInfo and call it with reflection
  • Pass in the name of the event (and the target if necessary) and call it with reflection
  • Pass in delegates for subscription and unsubscription

The call in the latter case would be something like:

SubscribeAndDoUnsubscribe(elements,                           handler => e.Click += handler,                           handler => e.Click -= handler); 

and the declaration would be:

void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(         IEnumerable<TElement> elements,         Action<EventHandler<TEventArgs>> subscription,         Action<EventHandler<TEventArgs>> unsubscription)     where TEventArgs: EventArgs 
like image 32
Jon Skeet Avatar answered Sep 23 '22 05:09

Jon Skeet