tags:

views:

312

answers:

3

basically:

public delegate void RecvCommandHandler (ChatApplication sender, byte[] content);
event RecvCommandHandler[] commands = new RecvCommandHandler[255];

I want to activate a different method/function for each command number, but I am really uncertain of the syntax. How am I supposed to do it?

I think I'll go with just an array of delegates for this one, but the question is still interesting.

+2  A: 

There's really no concept of an array of events - it's like talking about an array of properties. Events are really just methods which let you subscribe and unsubscribe handlers. If you need to be able to do this by index, I suggest you just have a pair of methods. (AddCommandHandler(int, RecvCommandHandler) and RemoveCommandHandler(int, RecvCommandHandler)). That won't support the normal event handling syntactic sugar, of course, but I don't see that there's a lot of alternative.

Jon Skeet
Just remark to intro -- I have no problem with Action[]. So it is possible to have array of methods, the problem is rather that event in C# behaves like some kind of hybrid of method and object. It should be normal class with un-/register methods and call.
macias
+1  A: 

The other option is to specify and index in the delegate prototype and have one event handler that "delegates" to the others, e.g.:

public delegate void RecvCommandHandler (int id, ChatApplication sender, byte[] content);

// ...

private RecvCommandHandler[] internalhandlers;

public void MyCommandHandler(int id, ChatApplication sender, byte[] content)
{
    internalHandlers[id](id, sender, content);
}
mjmarsh
A: 

I was just looking for the same answer, however my class is also event sender for WPF, so it should look as much as normal C#/WPF event sender class. So I simply added this:

To sender:

  • enum with properties name -- this is lame workaround for lack of nameof
  • one additional method to record requests

To receiver:

  • request event for given enum

The code, sender:

    public enum Properties
    {
        NetworkFileName,
        DatasetFileName,
        LearningWatch
    }

    private string network_filename;
    public string NetworkFileName 
    {
        get { return network_filename; }
        private set 
        {
            if (network_filename != value)
            {
                network_filename = value;
                OnPropertyChanged(Properties.NetworkFileName.ToString());
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public void OnChange(Properties prop, Action<object, PropertyChangedEventArgs> action)
    {
        PropertyChanged += new PropertyChangedEventHandler((obj, args) => { if (args.PropertyName == prop.ToString()) action(obj, args); });
    }

And to the receiver:

    private void OnNetworkLoaded(object sender, PropertyChangedEventArgs e)
    {
        SetTitle();
    }

        ...
        ExpManager.OnChange(ExperimentManager.Properties.DatasetFileName, OnDatasetLoaded);

It is still ugly, but at least:

  • I don't have to deal with "ifs" in receiver
  • I can easily create multiple event handlers
  • it is compatible with WPF
  • no magic strings (I hate those)

Disadvantage:

  • obsfuscation ruins this (but I have special class for that case, this project is just for me, so no problem here)
macias