在一開始接觸到這個名詞時
我也是一頭霧水
讓我們來看看官方文件怎麼寫
委派是一種類型,代表具有特定參數清單及傳回型別的方法參考。 當您具現化委派時,可以將其執行個體與任何具有>>相容簽章和傳回型別的方法產生關聯。 您可以透過委派執行個體叫用 (或呼叫) 方法。
看完之後有沒有比較了解委派在幹嘛(我那時候直接把滑鼠移到右上角的XX按下去)
以我的話解釋 委派其實是代替你執行某種方法(就是你要執行的那個,但你現在不知道要執行的是哪個),
事實上委派很像函式指標,裡面存著你要執行方法的記憶體位置
把你的游標從XX移開Orz
我們直接先來看看範例吧(我覺得從範例比較好懂)
我們在昨天的[Day7] 豪想要一種能接納所有人的型別 關於多載與泛型 文章中有提到方法簽章這個東西
再我們宣告委派的時候同樣有方法簽章
它是一樣是由傳入類型與回傳類型所決定
注意
在方法多載的內容中,方法的簽章並不包括傳回值。 不過在委派的內容中,簽章卻包含傳回值。 換句話說,方法必須與委派擁有相同的傳回類型。
我們先來建立一個委派 使用delegate 關鍵字:
public delegate 回傳類型 委派名稱(傳入參數);
跟方法不同沒有你的程式碼喔
因為委派是執行你的方法 不用再自定義了不然就直接用方法就好了
public delegate void PrintNumber(int num);
input為int output為void(不回傳)
然後我們來宣告2個方法 跟我們委派一樣的方法簽章
(input為int output為void)
public static void PrintOddNumber(int num){
Console.WriteLine("輸入的是奇數:"+num);
}
public static void PrintEvenNumber(int num){
Console.WriteLine("輸入的是偶數:"+num);
}
分別將委派指向兩個方法
void Main(){
int num = int.Parse(Console.ReadLine());
PrintNumber print;
if(num % 2 == 1){
print = PrintOddNumber;
//正規寫法是print = new PrintNumber(PrintOddNumber)
//上面是語法糖(寫起來比較簡潔)
}
else
{
print = PrintEvenNumber;
}
print(num);
}
啊我就直接在if else裡面呼叫方法就好了啊
事實上委派更常出現在跨類別的函式傳遞
或者式Callback裡
讓我們繼續看下去
麻煩請大家移駕到C# 事件(上) - 使用委派來實作事件去觀看
我覺得這篇文章對於事件的解釋非常容易了解
Action<> 跟 Func<TResult> 最大的差異是
若是不熟悉T請看上篇[Day7] 豪想要一種能接納所有人的型別 關於多載與泛型
它們一樣是委派
舉例來說
不帶參數的Action
using System;
namespace ConsoleApp1
{
class Program
{
static Action Test;
static void Main()
{
Test = Print;
Test();
}
public static void Print()
{
Console.WriteLine("你好");
}
}
}
//你好
帶參數的Action<int,int>
這邊的<int,int> 對應到 Add跟Sub的傳入參數
using System;
namespace ConsoleApp1
{
class Program
{
static Action<int,int> Calculate;
static void Main()
{
Calculate = Add;
Calculate(6, 5); //傳入型態為2個int 會執行 Add(5,6)
//num1 + num2 = 11
Calculate = Sub;
Calculate(6, 5); //會執行 Sub(5,6)
//num1 - num2 = 1
}
public static void Add(int num1, int num2)
{
Console.WriteLine($"num1 + num2 = {num1 + num2}");
}
public static void Sub(int num1, int num2)
{
Console.WriteLine($"num1 - num2 = {num1 - num2}");
}
}
}
不帶參數的Func<TResult>
這邊TResult對應回傳的string
using System;
namespace ConsoleApp1
{
class Program
{
private static Func<string> func;
static void Main()
{
func = GetHandSomeBoy;
func();
}
public static string GetHandSomeBoy()
{
return "Me";
}
}
}
//Me
帶傳入參數Func<int,int,string>
回傳類型為string 傳入參數為int,int
using System;
namespace ConsoleApp1
{
class Program
{
private static Func<int,int,string> Calculate;
static void Main()
{
Calculate = Add;
Console.WriteLine(Calculate(6, 5)); //傳入型態為2個int 會執行 Add(5,6)
//num1 + num2 = 11
Calculate = Sub;
Console.WriteLine(Calculate(6, 5)); //會執行 Sub(5,6)
//num1 - num2 = 1
}
public static string Add(int num1, int num2)
{
return $"num1 + num2 = {num1 + num2}";
}
public static string Sub(int num1, int num2)
{
return $"num1 - num2 = {num1 - num2}";
}
}
}
Action 跟 Fun 最高支援傳入16個參數的Method
Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult> 代理人
這不就來了嗎
事實上在事件裡面的那篇文章就是跨類別的傳遞
我根據他的例子簡單改寫成Action 與 Func
有一個路人類別
他有一個方法負責接收消息
Passenger.cs
using System;
namespace ConsoleApp1
{
public class Passenger
{
public void ReceiveNews(string news)
{
Console.WriteLine($"我收到一則新聞內容是:{news}");
}
}
}
還有我們的八卦版
負責放出新聞
Gossiping.cs
using System;
namespace ConsoleApp1
{
public class Gossiping
{
public void Notify(Action<string> action, string news)
{
action(news);
}
}
}
在某個小島國裡有一個八卦中心跟一名路人
八卦中心透過路人接受訊息的能力傳了一則訊息給他
Taiwan.cs
namespace ConsoleApp1
{
public class Taiwan
{
static void Main()
{
Gossiping gossiping = new Gossiping();
Passenger passenger = new Passenger();
gossiping.Notify(passenger.ReceiveNews, "開放美豬進口了");
}
}
}
透過接收者的方法不同能做不同的處理
我們再新增2個類別 一樣有他們自己的方法
FourPercent.cs
using System;
namespace ConsoleApp1
{
public class FourPercent
{
public void Argue(string message)
{
Console.WriteLine($"政府要{message},政府有夠爛");
}
}
}
Green.cs
using System;
namespace ConsoleApp1
{
public class Green
{
public void Support(string message)
{
Console.WriteLine($"Green:政府要{message},FourPercent好了拉,又死不了");
}
}
}
修改下Taiwan.cs 讓gossiping通知所有人
namespace ConsoleApp1
{
public class Taiwan
{
static void Main()
{
Gossiping gossiping = new Gossiping();
Passenger passenger = new Passenger();
FourPercent fourPercent = new FourPercent();
Green green = new Green();
string news = "開放美豬進口了";
gossiping.Notify(passenger.ReceiveNews, news);
gossiping.Notify(fourPercent.Argue, news);
gossiping.Notify(green.Support, news);
}
}
}