Handling Events Using C # Extension Methods

I recently learned how to use C # extension methods to facilitate calls, and I am using them more and more. I recently got into a strange problem that I don't understand, and I was wondering if anyone could explain this.

The problem occurs when you try to set the event handler extension method as the event handler of another event. Here is an example of what I am doing:

public static class EventHandlerExtensions { public static void Raise<TEventArgs>( this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs args) where TEventArgs:EventArgs { if (eventHandler != null) { eventHandler(sender, args); } } } public class Test { private event EventHandler<EventArgs> EventA; private event EventHandler<EventArgs> EventB; public Test() { Console.WriteLine("::Start"); EventB += EventA.Raise; EventA += (s, a) => Console.WriteLine("Event A raised"); EventB.Raise(this, EventArgs.Empty); Console.WriteLine("::End"); } } 

In this example, EventA should be triggered by an EventB. However, when I run this code, EventB fires, but the extension method to A does not find any listeners for it.

If I change the order around, everything will be fine:

 Console.WriteLine("::Start"); EventA += (s, a) => Console.WriteLine("Event A raised"); EventB += EventA.Raise; EventB.Raise(this, EventArgs.Empty); Console.WriteLine("::End"); 

Also, calling EventA.Raise from lambda works fine:

 Console.WriteLine("::Start"); EventB += (s, a) => EventA.Raise(s, a); EventA += (s, a) => Console.WriteLine("Event A raised"); EventB.Raise(this, EventArgs.Empty); Console.WriteLine("::End"); 

This is a simple example, but I'm trying to create a class that can redistribute events from event sources added to it in the cleanest way. I don’t want to create named methods just to resubmit the same events, and I would prefer not to store lists of lambda functions that I can detach from event handlers later. Basically, I'm just wondering why this is happening?

Any ideas?

+6
source share
2 answers

You commit the old EventA value in closing with the Raise function. Since you use + = later, it changes the value of EventA, but your closure still has the old value.

The code:

 EventB += EventA.Raise; EventA += (s, a) => Console.WriteLine("Event A raised"); 

It can be expanded into equivalent code, which makes it clear why you get the old delegate:

 var oldEventA = EventA; EventB += oldEventA.Raise; // captures old value here // now EventA changed to new value EventA = oldEventA + ((s, a) => Console.WriteLine("Event A raised");) 

You can add the following to EventB += EventA.Raise to check if the code is actually EventB += EventA.Raise old event for A:

 EventA += (s, a) => Console.WriteLine("Old Event A raised"); 
+4
source

Delegating objects are immutable. Very similar to strings. Therefore, when you assign EventA, you create a new object. EventB is still targeting the old, one that does not yet have an assigned event handler. You must change two statements to fix the problem.

+2
source

Source: https://habr.com/ru/post/916512/


All Articles