2017年6月21日 星期三

[C#] 把方法當作變數一樣傳遞:委派 Action 、Lambda 使用


在C#中 有個辦法能使「方法 Method」像是傳遞變數一樣讓某個方法去執行。
這個方法就叫做「委派」。

委派有四種形式可以使用「Delegate、Func、Action、Predicate」,
本文章單純示範最近我個人最近實作有用到的 Action。

延伸閱讀:C#委託的介紹

==========================================================

狀況:
  • 現有一個 4 * 4 的整數陣列 intArray。
  • 首先讓該陣列塞入1~100的亂數
  • 印出 陣列 intArray 全部數值
  • 印出 陣列 intArray 全部偶數值
  • 印出 陣列 intArray 全部奇數值
不會委派時,我會這樣寫上述的功能:
 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
62
63
64
65
66
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class main : MonoBehaviour
{
    public int[,] intArray = new int[4, 4];

    // Use this for initialization
    void Start()
    {
        fillIntArrayRandom();
    }

    //將 IntArray 以隨機0~100填滿
    void fillIntArrayRandom()
    {
        for (var x = 0; x < 4; x++)
        {
            for (var y = 0; y < 4; y++)
            {
                intArray[x, y] = Random.Range(0, 100);
            }
        }

    }
    //印出 IntArray
    void printIntArrayAll()
    {
        for (var x = 0; x < 4; x++)
        {
            for (var y = 0; y < 4; y++)
            {
                Debug.Log("x:" + x + "," + "y:" + y + "=" + intArray[x, y]);
            }
        }
    }
    //印出 IntArray 中的偶數
    void printIntArrayOnlyEven()
    {
        for (var x = 0; x < 4; x++)
        {
            for (var y = 0; y < 4; y++)
            {
                if (intArray[x, y] % 2 != 0) return;
                Debug.Log("x:" + x + "," + "y:" + y + "=" + intArray[x, y]);
            }
        }
    }
    //印出 IntArray 中的奇數
    void printIntArrayOnlyOdd()
    {
        for (var x = 0; x < 4; x++)
        {
            for (var y = 0; y < 4; y++)
            {
                if (intArray[x, y] % 2 == 0) return;
                Debug.Log("x:" + x + "," + "y:" + y + "=" + intArray[x, y]);
            }
        }
    }

}
但這樣寫法老實說有個地方非常的醜,就是在每個方法裡面我都重複寫了一個二維迴圈。
下面就用委派Action的方法來改進這一部份

使用委派Action改寫的版本:
 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
62
63
64
65
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;//在Unity中,如果要用委派action就要加這行       

public class main : MonoBehaviour
{
    public int[,] intArray = new int[4, 4];

    // Use this for initialization
    void Start()
    {
        fillIntArrayRandom();
    }
    //針對IntArray內每個int...
    void forEachIntArray(Action<int, int, int[,]> act)
    {
        for (var x = 0; x < 4; x++)
        {
            for (var y = 0; y < 4; y++)
            {
                act(x, y, intArray);
            }
        }
    }

    //將 IntArray 以隨機0~100填滿
    void fillIntArrayRandom()
    {
        Action<int, int, int[,]> act = (xx, yy, iArray) =>
        {
            iArray[xx, yy] = UnityEngine.Random.Range(0, 100);//因為加了using System ,所以Random前面要註明是使用UnityEngine的    
        };
        forEachIntArray(act);
    }
    //印出 IntArray
    void printIntArrayAll()
    {
        Action<int, int, int[,]> act = (xx, yy, iArray) =>
        {
            Debug.Log("x:" + xx + "," + "y:" + yy + "=" + intArray[xx, yy]);
        };
        forEachIntArray(act);
    }
    //印出 IntArray 中的偶數
    void printIntArrayOnlyEven()
    {
        Action<int, int, int[,]> act = (xx, yy, iArray) =>
        {
            if (intArray[xx, yy] % 2 != 0) return;
            Debug.Log("x:" + xx + "," + "y:" + yy + "=" + intArray[xx, yy]);
        };
        forEachIntArray(act);
    }
    //印出 IntArray 中的奇數
    void printIntArrayOnlyOdd()
    {
        Action<int, int, int[,]> act = (xx, yy, iArray) =>
        {
            if (intArray[xx, yy] % 2 == 0) return;
            Debug.Log("x:" + xx + "," + "y:" + yy + "=" + intArray[xx, yy]);
        };
        forEachIntArray(act);
    }
}

  • 為了要使用Action類型的委派,我們必須在第四行加入using System;
  • 加入 using System;後,使用 Random 時須指定使用 system 或UnityEngine的(32行
  • 在這版本中,二維迴圈都被整合到 forEachIntArray 這個方法中
  • forEachIntArray 接受一個委派參數,並將該參數在二維迴圈內執行。
我解釋很爛,大家可以自己挑戰微軟的說明...Lambda說明 
或是這篇解釋的蠻清楚跟仔細的....連結

沒有留言:

張貼留言