茅塞頓開的一晚-Func 委派+匿名方法+lambda
今天聽了同事講解Func,聽完覺得太酷了。
不過在紀錄之前,要先講一下 委派跟匿名方法。
委派在我自己的理解上,就是拜託他去幫你執行某個方法
當然拜託也要拜託對人,你所拜託的委派,要能做到你所要的方法(也就是傳回的型別,跟傳入的參數要一致)
這個想法還滿直觀的,例如現實中,你必須拜託某個朋友幫你挑女友的生日禮物
你一定挑個要嘛交過很多女朋友的人,不然就是挑個女生,比較懂該送甚麼
總不可能挑個阿宅,只想的到送遊戲點卡,還是漫畫之類的吧。當然修電腦找這種人不錯(我就是這個好人..)。
所以在建立委派時,這委派必須符合的你方法。
class Program
{
static void Main(string[] args)
{
//讀進要做的動作" + , - , * , / "
string s = Console.ReadLine();
//建立一個委派
MyDelegate d;
//依照傳入的動作,選擇要傳入委派的方法
switch (s)
{
case "+":
d = new MyDelegate(加法);
break;
case "-":
d = new MyDelegate(減法);
break;
case "*":
d = new MyDelegate(乘法);
break;
case "/":
d = new MyDelegate(除法);
break;
default:
d = new MyDelegate(加法);
break;
}
//使用該委派
int Answer = d(5, 2);
Console.WriteLine(Answer);
Console.ReadKey();
}
//用static是因為我懶的new出物件,但要視情況用
public static int 加法(int x, int y)
{
return (x + y);
}
public static int 減法(int x, int y)
{
return (x - y);
}
public static int 乘法(int x, int y)
{
return (x * y);
}
public static int 除法(int x, int y)
{
if (y != 0)
return (x / y);
return 0;
}
public delegate int MyDelegate(int x, int y);
}
上面的因為都是基本觀念,所以就咻咻咻的講完了。
接著講匿名方法,匿名方法就是不需要為了可能只用一次的方法
而建立類別實體和該方法,直接經由delegate關鍵字將方法傳入即可。
跟javascript的function有點類似,有時只用一次的function 就直接 xxx.click( function(){…})使用
因此改寫上面的Code 12~29行那段
switch (s)
{
case "+":
d = delegate(int x, int y)
{
return x + y;
};
break;
case "-":
d = (int x, int y) => { return x - y; };
break;
case "*":
d = (int x,int y) => x * y;
break;
case "/":
d = (x, y) => y != 0 ? x / y : 0;
break;
default:
d = new MyDelegate(加法);
break;
}
加法是用delegate關鍵字,然後傳入參數並在中括號中 return結果
減法省略delegate關鍵字,改用Lambda運算式的寫法
乘法連中括號和return都省了,直接寫要傳回的結果
除法連傳入的型別都可省略,因Lambda會自動推斷正確的型別
到這邊,就講完了委派、匿名方法,還提到一點Lambda了。
Lambda很好用,不過看起來太精簡所以有點難懂,基本格式是
(input parameters) => { expression }
左邊想成傳入方法的參數,用 " => " 運算子連接,右邊是 方法的內容。
接著講 Func 這個東西
依照昨天為了打個球跟我在外面流浪一整晚的同事(他不想曝光)的說法,
Func是微軟定義好的delegate
因此他跟delegate一樣
可以替以他為型別的變數指派一個方法
可以替以他為型別的變數指派一個方法
可以替以他為型別的變數指派一個方法
可以替以他為型別的變數指派一個方法
來看一個例子
public static int MyFunc(Func<int, int, int> fun, int x, int y)
{
return fun(x, y);
}
上面這個方法有三個參數,分別是 Func<int,int,int> fun, int x ,int y
第一個參數就是func,記得上面repeat好幾次的那句話嗎?Func可以替以他為型別的變數指派一個方法
所以就把 fun 當成一個可以 丟入方法的變數 來看,
而fun這個方法呢,要傳入兩個int型別的參數,並且回傳int型別的回傳值
接著看完整的範例
class Program
{
static void Main(string[] args)
{
string s = Console.ReadLine();
Func<int, int, int> f;
// 依照輸入的運算符號選擇要存的方法
// 記得!!Func<>是可以存方法的變數,
// 所以+我存了一個加法的方法
// -是用delegate存匿名方法
// *、/ 是用lambda存方法
switch (s)
{
case "+":
f = 加法;
break;
case "-":
f = delegate(int x, int y) { return x - y; };
break;
case "*":
f = (int x, int y) => x * y;
break;
case "/":
f = (x, y) => y != 0 ? x / y : 0;
break;
default:
f = 加法;
break;
}
//使用MyFunc方法
int answer = MyFunc(f, 5, 2);
//也可以這樣寫喔,傳入匿名的Func
//int answer = MyFunc((x, y) => x + y, 5, 5);
Console.WriteLine(answer);
Console.ReadKey();
}
public static int MyFunc(Func<int, int, int> fun, int x, int y)
{
return fun(x, y);
}
public static int 加法(int x, int y)
{
return (x + y);
}
}
呼,講完了。
整個過程不太好懂,因為等於是方法中又有方法。
但懂了之後,覺得有很趣。
雖然現在經驗不足,還不知道要用在哪裡比較適當,但學起來再說。