DAY 17 委派
委派
「委派型別」代表對方法的參考,其中含有特定參數清單與傳回型別。
委派讓您可將方法視為實體,而實體能指派給變數或當作參數來傳遞。
委派就類似其他程式設計語言中的函式指標,但與函式指標的不同之處是,委派是物件導向且為型別安全。
簡單來說 Delegate (委派)是將 function 當成參數傳遞的型別。
委派的方式有三種具名函式、匿名函式、Lambda運算式。
具名函式: 將已宣告的方法(
nameMethod
)指給委派匿名函式:
delegate (arguments) { statements }
delegate: 匿名函式的的保留字
arguments: 傳入參數的宣告,可以多個參數(以
,
隔開)statements: 此函式執行的程式碼片段
Lambda:
arguments => expression | block
arguments: 傳入參數的宣告,可以多個參數(以,隔開)。
只有一個參數時可以不用括號,多個參數時都要加上括號
可以不用明確指定型別
可以明確指定型別
明確指定型別時一定要加上括號
沒有傳入參數時用空括號
()
表示
expression: 運算式,不括大括號
{}
,只能單行程式碼,代表回傳值block:
{ statements }
: 程式碼區塊,statement
為此函式執行的程式碼片段
具名函式
委派需要事先宣告此委派類型的傳入參數與傳回值,至少 0 個參數,至多 32 個參數,可以無傳回值,也可以指定傳回值類型。
注意 參數與傳回型別需一致
1 | static void Main (string[] args) { |
匿名函式
使用匿名方法可以減少在具現化委派中撰寫程式碼的額外負荷,因為不必另外建立一個方法。
1 | static void Main (string[] args) { |
Lambda
以 lambda 運算式取代匿名方法,成為撰寫程式碼內嵌的慣用方式。
1 | static void Main (string[] args) { |
可以看到在減法方法中,lambda 甚至可以省去傳入參數的型別與 return 關鍵字。
委派的聲明
除了 Delegate 也可以使用 Action, Func, Predicate 這些類型來進行委派,不用事先宣告委派的類型。
Action
Action是無傳回值的泛型委派。
Action至少0個參數,至多16個參數。
1 | static void Main (string[] args) { |
Func
Func 是有傳回值的泛型委派。
Func 至少0個參數,至多16個參數,以及一個傳回值的型別參數。方法必須有傳回值,不可為 void。
Func<int> 無輸入的參數,且傳回值為 int 型別的委派。
Func<object,string,int> 表示傳入參數為 object , string 傳回值為 int 型別的委派。
1 | static void Main (string[] args) { |
使用 Func 委派時,也能用 Lambda 進行。
1 | static void Main (string[] args) { |
Predicate
Predicate 是返回 bool 型的泛型委派。
Predicate<int> 表示傳入參數為 int 返回 bool 的委派。
Predicate 有且只有一個參數,傳回值固定為 bool。
1 | static void Main (string[] args) { |
Lambda
這邊在多補充點有關 Lambda 的觀念,因為 Lambda 在目前的程式碼撰寫很容易會使用到。
Lambda 運算式是匿名函式,可用來建立委派或運算式樹狀架構類型。
使用 Lambda 運算式可以撰寫區域函式,這些函式可以當做引數傳遞,或是當做函式呼叫的值傳回。
Lambda 運算式對於撰寫 LINQ 查詢運算式而言特別有用。
題外話:LINQ 會在之後做介紹。
建立 Lambda 運算式,需在 Lambda 運算子(=>) 的左邊指定輸入參數 (如果有的話),並將運算式或陳述式區塊放在另一邊。
結構如:arguments => expression | block
(=>) 運算子與指派 (=) 具有相同的優先順序。
arguments
- 只有一個傳入參數時可以省略小括弧
()
1 | //Only one input parameter |
- 可以明確指定型別,明確指定型別時一定要加上括號
()
,不明確指定型別也可以
1 | string x => x * x //illegal |
- 沒有傳入參數時以空括號
()
表示
1 | () => Console.WriteLine("Hello Lambda") |
expression
- 只有單行程式碼時為
expression
,可以不用{}
包住程式,程式行的最後也不用加;
,其程式碼所代表的是回傳值
1 | x => x * x //delegate (int x) { return x * x; } |
- 使用
expression
格式的Lambda稱為Lambda運算式(Lambda Expressions)
block
- 一般的程式碼區塊,可以多行程式碼,每行最後要加
;
1 | x => { return x * x; } |
- 使用
block
格式的Lambda稱為Lambda陳述式(Lambda Statements)
一些小結論
今天介紹了委派,其實有點算是講古吧,但如果沒有基本觀念的話,直接使用也容易搞不懂在用什麼。上面也講過了,現在主流都是用 Lambda 了,尤其是操作 LINQ 時,幾乎每一句都是,所以 Lamda 是什麼,這邊也先告訴你了。
Lambda 也可以在宣告方法時使用如
1 | static int add2num (int a, int b) => a + b; |
所以與其說是教委派,更多的是 Lambda 的使用,但如果沒有委派的觀念,使用起 Lambda 時總會卡手卡腳的。
本來今天是想介紹泛型的,打到一半覺得還是先講委派好了,泛型後面接集合比較順,也可以不用再看一次類別。
感謝閱讀。
參考連結
C# 委派 - C# 語言教學課程 | Microsoft Docs
匿名方法 (C# 程式設計手冊) | Microsoft Docs
Lambda 運算式 (C# 程式設計手冊) | Microsoft Docs
C#委託的介紹(delegate、Action、Func、predicate) @ 資訊園 :: 痞客邦 ::