出處:http://www.dotblogs.com.tw/shadow/archive/2012/09/25/75039.aspx
先從簡單的開始講
原本的if else寫法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightApplication3
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
string userInput = "櫻桃";//使用者輸入的文字
if (userInput == "蘋果")
{
showApple();
}
else if (userInput == "香蕉")
{
showBanana();
}
else if (userInput == "櫻桃")
{
showCherry();
}
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
}
雖然先前提過[C#] 用反射(映射)移除if…else陳述式
可以用反射來移除if分支,但要是遇到輸入的字串是中文字,程式碼就得跟著使用中文命名,感覺怪怪的↓…
string userInput = "櫻桃";//使用者輸入的文字
Type t = Type.GetType("SilverlightApplication3.MyUserControl");
//拼接要執行method的名稱(中文)
string methodName = "嘻嘻哈哈";
object result = t.InvokeMember(methodName, BindingFlags.InvokeMethod, null, Activator.CreateInstance(t), null);
條件是字串的判斷
今天剛好遇到要寫很多分支條件判斷,發現如果只是單純的中文字串,應該可以把 條件和要做的Method 都先放入Dictionary中
再依據使用者輸入的字串,直接挑出目標Method來執行就好
所以上述程式碼可以改良(具名委派版)↓
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
public delegate void DoSomething();//宣告委派
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
string userInput = "櫻桃";//使用者輸入的文字
//把原本if要判斷的條件字串儲存在Key,由於原本的if條件本來就不會重覆,正適合當Key
//各個Key(條件)要執行的Method就儲存在Value
Dictionary<string, DoSomething> d = new Dictionary<string, DoSomething>()
{
{"蘋果", new DoSomething(showApple)},
{"香蕉", new DoSomething(showBanana)},
{"櫻桃", new DoSomething(showCherry)}};
d[userInput].Invoke();//直接挑選要執行的Method來執行
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
如果懶得宣告具名委派,寫得更簡潔的話↓
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
string userInput = "櫻桃";//使用者輸入的文字
Dictionary<string, Action> d = new Dictionary<string, Action>() {
{"蘋果", ()=>{ MessageBox.Show("Apple"); }}, //各條件要做的事....
{"香蕉", ()=>{ MessageBox.Show("Banana"); }},
{"櫻桃", ()=>{ MessageBox.Show("Cherry"); }}
};
d[userInput].Invoke();//直接挑選要執行的Method來執行
}
}
↑如此一來,各條件要做的事都很整齊地列出來,Code也變得比較乾淨。
條件是數字大小的判斷
但「if 也有判斷數字區間的情況,該怎麼辦呢?」
例如以下:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
if (userInput >= 1 && userInput <= 10)//在1到10的區間
{
showApple();
}
else if (userInput >= 11 && userInput <= 20)//在11到20的區間
{
showBanana();
}
else if (userInput >= 21 && userInput <= 30)//在21到30的區間
{
showCherry();
}
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
基本上也可以用Dictionary,也是把條件放在Key的位置,要做的事放在Value
條件式會回傳true Or false,所以就可以利用Linq挑選出Key回傳值為true的Value(Method)來執行即可
如下:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
public delegate bool MyKey(int userInput);
public delegate void MyValue();
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
Dictionary<MyKey, MyValue> d = new Dictionary<MyKey, MyValue>()
{
{new MyKey(condition1), new MyValue(showApple) },//各條件要做的事....
{new MyKey(condition2), new MyValue(showBanana)},
{new MyKey(condition3), new MyValue(showCherry)},
};
//挑選出Key的回傳值為true的Method來執行
d.Where(x => x.Key(userInput) == true).FirstOrDefault().Value.Invoke();
}
//把條件抽出成Method
private bool condition1(int i)
{
return (i>=1 && i<=10);
}
private bool condition2(int i)
{
return (i >= 11 && i <= 20);
}
private bool condition3(int i)
{
return (i >= 21 && i <= 30);
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
簡潔寫法:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
Dictionary<Func<int, bool>, Action> d = new Dictionary<Func<int, bool>, Action>() {
{ (a)=>{return (a >= 1 && a <= 10);}, ()=>{ MessageBox.Show("Apple"); }}, //各條件要做的事....
{ (a)=>{return (a >= 11 && a <= 20);}, ()=>{ MessageBox.Show("Banana"); }},
{ (a)=>{return (a >= 21 && a <= 30);}, ()=>{ MessageBox.Show("Cherry"); }}
};
//挑選出Key回傳值為true的Method來執行
d.Where(x => x.Key(userInput) == true).FirstOrDefault().Value.Invoke();
}
多個條件符合的判斷
看完以上兩個例子,再來假設一點
如果有符合多個條件的情況,如下:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
//這次把else移掉,每個if都會進行判斷,並且有兩個條件符合
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
if(userInput>0)
{
showPlus();
}
if (userInput >= 1 && userInput <= 10)//在1到10的區間
{
showApple();
}
if (userInput >= 11 && userInput <= 20)//在11到20的區間
{
showBanana();
}
if (userInput >= 21 && userInput <= 30)//在21到30的區間
{
showCherry();
}
}
private void showPlus()
{
//Do plus something...
MessageBox.Show("Plus");
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
也是可以改寫成如下:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
public delegate bool MyKey(int userInput);
public delegate void MyValue();
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
Dictionary<MyKey, MyValue> d = new Dictionary<MyKey, MyValue>()
{
{new MyKey(isPlus), new MyValue(showPlus)},
{new MyKey(condition1), new MyValue(showApple) },//各條件要做的事....
{new MyKey(condition2), new MyValue(showBanana)},
{new MyKey(condition3), new MyValue(showCherry)},
};
//※只是把原本的.FirstOrDefault(),改成foreach走訪每筆物件,並在迴圈中執行Method即可
//挑選出Key回傳值為true的Method來執行,並注意集合內的物件順序就是Method執行順序
foreach (KeyValuePair<MyKey,MyValue> item in d.Where(x => x.Key(userInput) == true))
{
item.Value.Invoke();
}
}
//把條件抽出成Method
private bool isPlus(int i)
{
return i > 0;
}
private bool condition1(int i)
{
return (i >= 1 && i <= 10);
}
private bool condition2(int i)
{
return (i >= 11 && i <= 20);
}
private bool condition3(int i)
{
return (i >= 21 && i <= 30);
}
private void showPlus()
{
//Do plus something...
MessageBox.Show("Plus");
}
private void showApple()
{
//Do Apple something...
MessageBox.Show("Apple");
}
private void showBanana()
{
//Do Banana something...
MessageBox.Show("Banana");
}
private void showCherry()
{
//Do Cherry something...
MessageBox.Show("Cherry");
}
}
簡潔寫法:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
int userInput = 14;//使用者輸入的文字
Dictionary<Func<int, bool>, Action> d = new Dictionary<Func<int, bool>, Action>() {
{(a)=>{ return (a > 0);} , ()=>{ MessageBox.Show("Plus"); }},
{ (a)=>{return (a >= 1 && a <= 10);}, ()=>{ MessageBox.Show("Apple"); }}, //各條件要做的事....
{ (a)=>{return (a >= 11 && a <= 20);}, ()=>{ MessageBox.Show("Banana"); }},
{ (a)=>{return (a >= 21 && a <= 30);}, ()=>{ MessageBox.Show("Cherry"); }}
};
//※只是把原本的.FirstOrDefault(),改成foreach走訪每筆物件,並在迴圈中執行Method即可
//挑選出Key回傳值為true的Method來執行
foreach (KeyValuePair<Func<int, bool>, Action> item in d.Where(x => x.Key(userInput) == true))
{
item.Value.Invoke();
}
}
}
複合式條件的判斷
如果原本的if else要判斷的條件很複雜,如下:
..............(略,看原文)