Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pass an event to a function in C#?

Tags:

I am looking to pass an event to a helper function. This function will attach a method to the event. However, I am having trouble properly passing the event. I have tried passing a EventHandler<TEventArgs>. It compiles, but events are not attached (but are still added; it seems a copy of the event handler is made).

For example, if I have this:

public event EventHandler<EventArgs> MyEvent;

And the helper function:

public static void MyHelperFunction<TEventArgs>(EventHandler<TEventArgs> eventToAttachTo)
{
    eventToAttachTo += (sender, e) => { Console.WriteLine("Hello world"); };
}

And the caller:

MyHelperFunction(MyEvent);
MyEvent(null, new EventArgs()); // Does nothing.
like image 681
strager Avatar asked Mar 08 '09 15:03

strager


People also ask

How do you pass a function as a parameter in C#?

If we want to pass a function that does not return a value, we have to use the Action<> delegate in C#. The Action<T> delegate works just like the function delegate; it is used to define a function with the T parameter. We can use the Action<> delegate to pass a function as a parameter to another function.


2 Answers

The reason why this does not work is += when applied to a delegate creates a new delegate which is the combination of the old and the new. It does not modify the existing delegate.

In order to get this to work you will have to pass the delegate by reference.

public static void Helper(ref EventHandler<EventArgs> e)
{
    e+= (x,y) => {};
}

The reason this works outside of the method is because the LHS is still the actual field. So += will create a new delegate and assign back to the member field.

like image 153
JaredPar Avatar answered Oct 06 '22 16:10

JaredPar


Just came up with this little helper. If it is your self-created Event you could use a wrapper like this. You can use your += operators to attach handlers as normal but can pass the wrapper around and even raise the event from elsewhere.

public class GenericEvent<T> where T:EventArgs
{
    public event EventHandler<T> Source = delegate { };

    public void Raise(object sender, T arg = default(T))
    {
        Source(sender, arg);
    }

    public void Raise(T arg = default(T))
    {
        Source(this, arg);
    }

    public void AddHandler(EventHandler<T> handler)
    {
        Source += handler;
    }

    public void RemoveHandler(EventHandler<T> handler)
    {
        Source -= handler;
    }

    public static GenericEvent<T> operator +(GenericEvent<T> genericEvent, EventHandler<T> handler)
    {
        genericEvent.AddHandler(handler);
        return genericEvent;
    }
}

Create the event like:

public GenericEvent<EventArgs> MyEvent = new GenericEvent<EventArgs>();

Attach handlers:

MyEvent += (s,e) => {};

Raise event:

MyEvent.Raise();
like image 39
Sven Avatar answered Oct 06 '22 16:10

Sven