switch-case語句是我們編碼過程中常用的一種分支語句。然而正所謂成也蕭何敗蕭何,每當我們向一個已經擁有了成百上千行的switch-case代碼段中添加新的case分支的時候,我們是否有過為代碼的可讀性和可維護性不斷下降而頭疼煩惱呢。
事實上,我們可以有很多方法來避免出現這種分支有多又長的switch-case代碼段,從而寫出更優美的代碼。在.Net中我們可以非常簡單地分解switch-case中的代碼。
下面選擇了一個比較常見的例子:模塊采用switch-case來處理接收到的Command
假設我們現在定義了以下10個CommandID。
CommandID下面我們定義了CommandHandler1類來處理這些命令。該類采用switch-case語句分別處理不同的CommandID。我們可以將每個CommandID的處理邏輯封裝在各個函數中(這裡偷懶,假設Math裡面定義的幾個方法就是我們封裝的處理邏輯),然後在每個case中調用相應的函數即可。
CommandHandler1在CommandHandler1中,我們如果新增了一個命令,那麼就需要增加一個處理新命令的方法,同時修改HandleCommand方法體,在其中添加一個case分支並調用新增的方法。
下面利用字典和委托CommandHandler1裡面的switch-case代碼段。我們新定義了一個類CommandHandler2,將處理每個CommandID的委托方法保存在一個字典表中(cmdHandlers),在HandleCommand方法體中,通過cmdID找到對應的委托方法來處理響應的cmdID。
CommandHandler2當我們新增一個命令時,只需要增加一個處理新命令的方法,同時將這個新命令及其對應的委托方法添加到字典表中即可。
下面我們來看一下這兩種方法的性能。在測試性能時,我們將所有的cmd處理方法全都替換成了HandleDefaultCommand。
Performance Test原本認為采用字典表+委托的方法性能應該比switch-case高,但測試結果卻令人失望(CommandHandler1比CommandHandler2反而高了近50%)。分析這裡面可能的原因:
1. 通過委托調度處理方法比直接調用方法效率相對較低;
2. 編譯器對switch-case的代碼進行了一定的優化。
好在一般對這裡的性能要求不是很高,100W次平均下來相差零點幾微秒,而在又多又長的switch-case代碼段中,一般是可以接受的。而對於比較簡短的switch-case代碼段,也就沒有必要采用第二種方式去替換了。
當然這裡所舉的處理Command的例子,有更好的解決方案。由於這篇文章只是講述如何用一種更優美的方式來替代switch-case,因此就不再詳細描述了。