2018年5月28日 星期一

函式傳遞的進化論 (3) - delegate

C#也是物件導向程式語言家族中的一員,因此同樣無法直接將方法傳遞給另一個方法。
C#同樣可以使用interface的技巧來包覆方法,不過這邊將介紹C#本身提供的方式:delegate(委派)
Delegate有一點像C的function pointer,其作用就是可以接收與傳遞方法。

首先使用關鍵字delegate來宣告一個delegate的類別
public delegate int Comparator(int first, int second);
這邊宣告名為Comparator的delegate類別,Comparator將會接受一種"參數是2個int並回傳1個int"的這種方法。


接著宣告一個方法可以接收Comparator類別,此方法會調用指派給委派物件的方法(有點繞口,讓我們看接下來的程式碼)
public void BubbleSort(int[] array, Comparator c)
    {
        for(var round=0; round < array.Length; round++)
        {
            for(var i=0; i<array.Length-1; i++)
            {
                if(c(array[i], array[i+1]) > 0)
                {
                    var temp = array[i];
                    array[i] = array[i+1];
                    array[i+1] = temp;
                }
            }
        }
    }
在第7行時呼叫此Comparator所接收到的方法。


接下來我們要宣告符合Comparator的方法:
public int SortByAsc(int first, int second)
    {
        if(first < second)
        {
            return -1;
        }
        else if(first > second)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }


然後在呼叫bubbleSort時將此方法傳遞給Comparator物件
public static void Main()
    {
        var array = new [] {4,7,1,6,9};
        var sorter = new Sorter();
        sorter.BubbleSort(array, sorter.SortByAsc);
        
        foreach(var elem in array)
        {
            Console.WriteLine(elem);
        }
        
    }


整體完整的程式如下:
using System.IO;
using System;

public delegate int Comparator(int first, int second);

public class Sorter
{
    public static void Main()
    {
        var array = new int[] {4,7,1,6,9};
        var sorter = new Sorter();
        sorter.BubbleSort(array, sorter.SortByAsc);
        
        foreach(var elem in array)
        {
            Console.WriteLine(elem);
        }
        
    }
    
    public void BubbleSort(int[] array, Comparator c)
    {
        for(var round=0; round < array.Length; round++)
        {
            for(var i=0; i<array.Length-1; i++)
            {
                if(c(array[i], array[i+1]) > 0)
                {
                    var temp = array[i];
                    array[i] = array[i+1];
                    array[i+1] = temp;
                }
            }
        }
    }

    public int SortByAsc(int first, int second)
    {
        if(first < second)
        {
            return -1;
        }
        else if(first > second)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

我們重新再看一次此程式。
首先先宣告一個委派類別Comparator(line 4),接著宣告符合此委派類別的方法SortByAsc(line 37)。
在第12行時將SortByAsc方法傳遞給BubbleSort的第二個引數Comparator c,
而BubbleSort會在第27行時呼叫c所接收到的方法,即sorter.SortByAsc方法

沒有留言:

張貼留言