Home [C# 筆記] 委託 Delegate
Post
Cancel

[C# 筆記] 委託 Delegate

委託 Delegate

  • 委託:是一種「引用類型」變量,用於儲存某個方法的「引用地址」。

定義格式:

1
public delegate 返回值類型 委託類型名字(參數類型1 參數名字,參數類型2 參數名字, ...)

只關心輸入、輸出,所以輸入、輸出就決定了一個方法的簽名

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
//聲明了一種數據類型(委託類型)叫做Calculate,代表的是某一類方法
public delegate int Calculate(int x, int y);

static int Add(int x, int y) { 
    return x + y;
}
static int Multiply(int x, int y) {
    return x * y;
}
.....

Calculate calc1 = new Calculate(Add); //calc1存放Add方法的地址
Calculate calc2 = new Calculate(Multiply); //calc2存放Multiply方法的地址

調用委託方法(invoke或())

invoke調用委託方法與 ()直接調用相同

1
2
3
4
//調用Add方法
calc1.invoke(1,2);
//調用Multiply方法
calc2(1,2)

代理給他=委託

  • calc1 是什麼意思呢?Calculate己經被聲明為一種數據類型,那麼就代表可以用它來聲明一個變量
  • new 一個 Calculate 類型的委託對象/物件
  • 它裡面存放一個 Add 方法的地址
  • 也就是說calc1 變量存放一個Add方法
  • calc2 變量存放一個Multiply方法

練習

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * 委託
 *  概念:是一種「引用類型」的變量,儲存某一個方法的內存地址
 */

namespace Delegate
{
    internal class Program
    {
        //聲明了一種數據類型(委託類型) 叫做Calculate,代表的是某一類方法
        //輸入: int, int,輸出: int
        public delegate int Calculate(int x, int y);
        static void Main(string[] args)
        {
            //直接調用Add方法
            //int sum = Add(1, 2);

            Calculate calc1 = new Calculate(Add);
            Calculate calc2 = new Calculate(Multiply);

            int sum = calc1.Invoke(1, 2);
            Console.WriteLine(sum);

            int mul = calc2(1, 2);
            Console.WriteLine(mul);

            Console.Read();
        }
        public static int Add(int x, int y) {
            return x + y;
        }
        public static int Multiply(int x, int y) {
            return x * y;
        }
    }
}

委託存在的意義

  • 回調方法(CallBack Method):當某個任執行完畢後,或者某事件觸發後,調用的方法。

遊戲

例如遊戲介面上有很多的 Button

  • 按鈕們彼此只有外觀不同,所以肯定是同一個 Class Button 通過 new 出來的對象/物件
  • 按鈕們被點擊之後,所執行的任務彼此不同,即調用了不同的響應方法
  • 按鈕對象中會保存一個回調方法,當點擊後調用此回調方法
1
2
3
4
5
6
7
8
9
10
class Button {
    //聲明一種委託類型OnClickDelegate
    public delegate void OnClickDelegate();
    ......
    //用OnClickDelegate這個數據類型,聲明了一個對象/物件OnClick
    public OnClickDelegate OnClick = null;
    ......
    //如果有點擊的事件發生,就去調用OnClick這樣一個委託,讓它去執行它所包含函數
    public void Click() { OnClick(); }
}

實作演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
 * 委託
 *  概念:是一種「引用類型」的變量,儲存某一個方法的內存地址
 */
namespace Delegate
{
    //1. 場景上所有的按鈕,都是當前Button類別 實體化的物件
    //2. 每個按鈕點擊後,發生的事情都不一樣
    //3. 每個按鈕點擊後,發生的事情由外界決定
    class Button
    {
        //1.聲明一個點擊消息響應的方法類型簽名(委託)
        public delegate void OnClickDelegate();

        //2.聲明一個OnClickDelegate類型的委託
        public OnClickDelegate onclick = null;

        //3.在點擊事件後,調用onClick委託儲存的方法
        public void Click() 
        {
            Console.WriteLine("按鈕被點擊了");
            if (onclick != null) onclick();
        }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            //遊戲開始
            Button gameStartButton = new Button();
            gameStartButton.onclick = new Button.OnClickDelegate(OnGameStart);
            gameStartButton.Click();

            //分享給好友
            Button friendButton = new Button();
            friendButton.onclick = new Button.OnClickDelegate(OnFriend);
            friendButton.Click();

            Console.Read();
        }

        //點擊了「遊戲開始按鈕」而觸發的方法
        public static void OnGameStart() {
            Console.WriteLine("遊戲開始");
        }
        public static void OnFriend() {
            Console.WriteLine("分享給好友");
        }
    }
}

試驗不同角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/// <summary>
/// 控制遊戲流程的類別
/// </summary>
internal class GameController
{
    public string name = "";

    public GameController() { }

    //遊戲開始
    public void OnGameStart() {
        Console.WriteLine($"{name} 遊戲開始");
    }
    //分享給好友
    public void OnFriend() {
        Console.WriteLine($"{name} 分享給好友");
    }
}

//1. 場景上所有的按鈕,都是當前Button類別 實體化的物件
//2. 每個按鈕點擊後,發生的事情都不一樣
//3. 每個按鈕點擊後,發生的事情由外界決定
class Button
{
    //1.聲明一個點擊消息響應的方法類型簽名(委託)
    public delegate void OnClickDelegate();

    //2.聲明一個OnClickDelegate類型的委託
    public OnClickDelegate onclick = null;

    //3.在點擊事件後,調用onClick委託儲存的方法
    public void Click() {
        Console.WriteLine("按鈕被點擊了");
        if (onclick != null) onclick();
    }
}
internal class Program
{
    //聲明了一種數據類型(委託類型) 叫做Calculate,代表的是某一類方法
    //輸入: int, int,輸出: int
    public delegate int Calculate(int x, int y);
    static void Main(string[] args)
    {
        GameController gameController1 = new GameController();
        gameController1.name = "Rii";
        GameController gameController2 = new GameController();
        gameController2.name = "Rivaaa";

        //遊戲開始
        Button gameStartButton = new Button();
        gameStartButton.onclick = new Button.OnClickDelegate(gameController1.OnGameStart);
        gameStartButton.Click();

        //分享給好友
        Button friendButton = new Button();
        friendButton.onclick = new Button.OnClickDelegate(gameController2.OnFriend);
        friendButton.Click();

        Console.Read();
    }
}

委託存在的意義二次思索

  • 需求:把 Button類,寫成一個獨立的C#文件,然後可以在其他項目中使用

  • 不用Delegate

1
2
3
4
5
6
7
class StartButton {
    public void OnClick() {
        //開始遊戲的邏輯
        Game game = new Game();
        GameMap map = new GameMap();
    }
}

Game類和GameMap類只存在於當前項目中

Button內部應該是乾淨的,無與項目其他類無關的內容!

1
2
3
4
5
6
7
8
9
class Button {
    public delegate void OnClickDelegate();
    ......
    public OnClickDelegate onClick = null;
    ......
    public void Click() {
        if(onClick != null) onClick();
    }
}

https://www.bilibili.com/video/BV1TP411R72r

This post is licensed under CC BY 4.0 by the author.

[C# 筆記] 泛型約束

[C# 筆記] 多播委託 Multicast-Delegate