コマンドマップ

ふと、思いました。

class Program
{
    static void ActionA()
    {
        Console.WriteLine("Action A.");
    }
 
    static void ActionB()
    {
        Console.WriteLine("Action B.");
    }
 
    static void ActionC()
    {
        Console.WriteLine("Action C.");
    }
 
    static void Main(string[] args)
    {
        do
        {
            // コマンド入力
            Console.Write("Input Cmd> ");
            string cmd = Console.ReadLine();
            switch (cmd)
            {
                case "A":
                    // Aコマンドを実行
                    ActionA();
                    break;
 
                case "B":
                    // Bコマンドを実行
                    ActionB();
                    break;
 
                case "C":
                    // Cコマンドを実行
                    ActionC();
                    break;
                default:
                    break;
            }
        }
        while (true);
    }
}

上記のサンプルような場合、コマンド増えるごとに、判断する箇所が増えていく・・・
もっと、シンプルに簡単にならないものか?と。

シンプルかつ、簡単にできるなら、後からの追加変更とか容易だし、修正によるバグも少なくなるのでは??
という建前の元、考えてみました。
本当は、コードの量が多く汚くなりそうなんで、嫌だなって単なる我が儘です(笑)

/// <summary>
/// コマンドMap
/// </summary>
static Dictionary<string, Action> _actionMap = new Dictionary<string, Action>();
 
static void Main(string[] args)
{
    // コマンドを登録
    _actionMap.Add("A", new Action(ActionA));
    _actionMap.Add("B", new Action(ActionB));
    _actionMap.Add("C", new Action(ActionC));
 
    do
    {
        // コマンド入力
        Console.Write("Input Cmd> ");
        string cmd = Console.ReadLine();
        if (_actionMap.ContainsKey(cmd))
        {
            // コマンド実行
            _actionMap[cmd]();
        }
    }
    while (true);
}

Actionは、.Net3.5で定義されているdelegateのGenericです。
戻り値なしで、引数4個までなら、デフォルトであります。

要は、コマンドと実行メソッドをDictionaryで管理し、実行時にコマンドをキーにして、実行メソッドを呼び出すという仕組み。
これで、増えた場合は、対象のメソッドを作成し、Dictionaryに追加する。消す場合は、Dictionaryの追加部分を削除するだけで、対応できる。
呼び出す部分も、増えていかず、きれいさっぱりに!(笑)

別途、専用にdelegateを定義して行えば、.Net2.0でも、戻り値ありも、引数ありも可能です。
ただし、コマンドの引数、戻り値が共通になっている必要がありますが。