1

This question covers the use of actions in a dictionary. I want to do something similar, but with more than one method per action:

static readonly Dictionary<char, Action[]> morseDictionary = new Dictionary<char,Action[]>
        {
            { 'a', new Action[] {dot, dash} },
            { 'b', new Action[] {dash, dot, dot, dot} },
            { 'c', new Action[] {dash, dot, dash, dot} },
            { 'd', new Action[] {dash, dot, dot} },
            { 'e', new Action[] {dot} }
            // etc
        };

dot and dash refer to these private functions:

private static void dash(){
    Console.Beep(300, timeUnit*3);
}

private static void dot(){
    Console.Beep(300, timeUnit);
}

I have another function, morseThis, which is designed to convert a message string to audio output:

private static void morseThis(string message){
    char[] messageComponents = message.ToCharArray();
    if (morseDictionary.ContainsKey(messageComponents[i])){
        Action[] currentMorseArray = morseDictionary[messageComponents[i]];
        Console.WriteLine(currentMorseArray); // prints "System.Action[]"
    }       
}

In the example above, I am able to print "System.Action[]" to the console for every letter contained in the input message. However, my intention is to call the methods within currentMorseArray in order.

How do I access the methods contained within a given Action[] in my dictionary?

Community
  • 1
  • 1
Candlejack
  • 448
  • 10
  • 23
  • 1
    For your specific case I would just store a lamda as the (single) action. So `... { 'a', () => { dot(); dash(); }, ...`. That keeps the invocation simple and doesn't really change the dictionary setup all that much. You might also consider making the field's type IReadOnlyDictionary, given that I don't think its contents are intended to be changed. – Zastai Oct 20 '15 at 17:07

4 Answers4

2

You're nearly there. You've got an array of actions, so now all you need to do is execute the actions in order.

Actions and Funcs in C# are just like any other object - you can put them in arrays, assign them to variables, pass them to methods as arguments, and so on. The only difference is that you can call an action. The syntax for this looks just like the syntax for calling a method:

Action myAction = ...
myAction();  // call the action

So to execute the actions in your array, you can just foreach down the array to pull them out one by one, and call each one in the body of the loop.

private static void morseThis(string message)
{
    char[] messageComponents = message.ToCharArray();

    if (morseDictionary.ContainsKey(messageComponents[i]))
    {
        Action[] currentMorseArray = morseDictionary[messageComponents[i]];

        foreach (Action action in currentMorseArray)
        {
            action();
        }
    }       
}
Benjamin Hodgson
  • 42,952
  • 15
  • 108
  • 157
2

Enumerate the actions and execute them.

private static void morseThis(string message)
{
    char[] messageComponents = message.ToCharArray();

    foreach(char c in messageComponents)
    {
        Action[] actions;

        if (morseDictionary.TryGetValue(c, out actions))
        {
            foreach(Action action in actions)
            {
              action();
            }
        }
    }
}
Trevor Ash
  • 623
  • 4
  • 8
2

Use foreach to iterate over array of actions:

private static void morseThis(string message){
    char[] messageComponents = message.ToCharArray();
    Action[] currentMorseArray;
    if (morseDictionary.TryGetValue(messageComponents[i], out currentMorseArray))
    {
        foreach(var action in currentMorseArray)
        {
            action();
        }
    }       
}

I'm not sure what you expected from Console.WriteLine, but behavior you observe is expected as WriteLine calls ToString on the object to print it and for arrays (and other types where ToString is not overridden) it simply returns type name.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
0
static readonly Dictionary<char, List<Action>> morseDictionary = new Dictionary<char,List<Action>>
        {
            { 'a', new List<Action> {dot, dash} },
            { 'b', new List<Action> {dash, dot, dot, dot} },
            { 'c', new List<Action> {dash, dot, dash, dot} },
            { 'd', new List<Action> {dash, dot, dot} },
            { 'e', new List<Action> {dot} }
            // etc
        };

private static void morseThis(string messageSrc)
{
    foreach(char message in messageSrc.ToCharArray())
    {
        List<Action> currentMorseArray;
        if (morseDictionary.TryGetValue(message, out currentMorseArray))
        {
            currentMorseArray.ForEach(x=>x());
        }   
    }    
}
burning_LEGION
  • 13,246
  • 8
  • 40
  • 52