Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an event from a function

Tags:

c#

events

What is the syntax to return an event from a function? (Not to call the event, to return it so that it can be bound to functions).

I have a container class that contains a dictionary where each members has an event.

The aim is to be able to write something like this:

Container c = new Container();
c.CreateEventForKey("a");             // Create the member in the dictionary
c.EventForKey("a") += some_function;  // Bind some_function to the event in the "a" member
c.OnEventForKey("a","b");             // Calls some_function with argument "b"

The Container class looks like this:

public class Container {

  public class Member {
     public event Action<string> AnEvent;
     public void OnEvent( string v ) { if(AnEvent!=null) { AnEvent(v); } }
  }

  protected Dictionary<string,Member> members;

  // This seems to work OK.
  public void OnEventForKey(string k, string v) {
    if ( members.ContainsKey(k) ) { members[k].OnEvent(v); }
    else { /* report error */ }
  }

  // Can't get this to compile.
  public event Action<string> EventForKey(string k ) {
    if ( members.ContainsKey(k) ) { return members[k].AnEvent; }
    else { /* report error */ }
  }
}

How can I define EventForKey so that this does what I expect?

like image 440
Michael Anderson Avatar asked Apr 21 '12 07:04

Michael Anderson


People also ask

How do I return a result from a function?

To return a value from a function, you must include a return statement, followed by the value to be returned, before the function's end statement. If you do not include a return statement or if you do not specify a value after the keyword return, the value returned by the function is unpredictable.

Can we return from a JavaScript function?

We can return primitive values (such as Boolean, number, string, etc.) and Object types (such as functions, objects, arrays, etc.) by using the return statement. We can also return multiple values using the return statement.

What is the return of a function?

A return is a value that a function returns to the calling script or function when it completes its task. A return value can be any one of the four variable types: handle, integer, object, or string. The type of value your function returns depends largely on the task it performs.

What is return () in JavaScript?

The return statement ends function execution and specifies a value to be returned to the function caller.


2 Answers

What is the syntax to return an event from a function?

You can't, easily. Events - like properties - aren't really first class "objects" as such; they're members of a class. You don't really have a class member here - you're trying to just keep delegates in a dictionary.

You could create your own "event-like" container, but it's probably better to consider alternative designs, e.g.

c.Subscribe("a", SomeFunction);
c.OnEventForKey("a");

You might want to look at EventHandlerList for inspiration.

like image 170
Jon Skeet Avatar answered Oct 18 '22 10:10

Jon Skeet


Why not simply return member and subscribe to it's event?

public IMember MemberForKey(string key) // return IMember
{
    if (!members.ContainsKey(key))
        throw new Exception();

    return members[key];
}

And then subscribe:

Container c = new Container();
c.CreateEventForKey("a");            
c.MemberForKey("a").AnEvent += some_function;
c.OnEventForKey("a", "b"); 

But you have public OnEvent method in Member class. In order to forbid raising events by client, you can create interface which will show only event. Just implement this interface by Member class:

public interface IMember
{
    event Action<string> AnEvent;
} 

And yes, you cannot return event, because actually event is not object, it is set of two methods add and remove, which add and remove delegates to inner field of delegate type. Here is how your event looks like:

  private Action<string> _action; // field of delegate type

  public event Action<string> AnEvent
  { 
      add { _action += value; }
      remove { _action -= value; }
  }

Purpose of event is to provide only two operations for clients - adding and removing handlers. Delegate itself is hidden to clients. You can make it public:

public Action<string> _action;

But in this case any client can invoke it.

UPDATE: if you want to go with Subscribe/Remove syntax, then just use dictionary with handlers:

public class Container
{
    private Dictionary<string, Action<string>> handlers = 
            new Dictionary<string, Action<string>>();

    public void CreateEventForKey(string key)
    {
        // with empty handler added you can avoid null check
        handlers.Add(key, (value) => { });
    }

    public void OnEventForKey(string key, string value)
    {
        if (!handlers.ContainsKey(key))
            throw new Exception();

        handlers[key](value);
    }

    public void Subscribe(string key, Action<string> handler)
    {
        if (!handlers.ContainsKey(key))
            throw new Exception();

        handlers[key] += handler;
    }
}
like image 2
Sergey Berezovskiy Avatar answered Oct 18 '22 10:10

Sergey Berezovskiy