C#筆記 委託 事件 匿名方法 Action

事件Event
實現的類似觀察者設計模式,一對多的通知。
相當於c++的函數指針的一個列表。
Event在UI上的事件回調用途很常見,代碼如下:

public class EventManager : MonoBehaviour 
{
    public delegate void ClickAction();
    public static event ClickAction OnClicked;

    void OnGUI()
    {
        if(GUI.Button(new Rect(Screen.width / 2 - 50, 5, 100, 30), "Click"))
        {
            if(OnClicked != null)
                OnClicked();
        }
    }
}

// 收到點擊事件隨機改變顏色
public class TurnColorScript : MonoBehaviour 
{
    void OnEnable()
    {
        EventManager.OnClicked += TurnColor;
    }
    void OnDisable()
    {
        EventManager.OnClicked -= TurnColor;
    }
    void TurnColor()
    {
        Color col = new Color(Random.value, Random.value, Random.value);
        renderer.material.color = col;
    }
}

事件和委託的區別
還是上面代碼,如果去掉event關鍵字也工作正常,這就是委託了……
區別在於加了event後只能用”+= -=“來添加或移除處理回調而”=“不成,如果寫 EventManager.OnClicked = TurnColor;編譯時就會報錯。

這樣在一定程度上保證了event系統在一個事件觸發後感興趣的系統都會得到通知,而不會被一個錯誤的賦值把別的已經註冊的處理都覆蓋掉。

匿名函數
c#1(版本)時即使要做的事情非常簡單也必須要有一個專門的做這件事情的方法,因此要爲這個方法創建一個委託實例。
c#2使用匿名方法對此進行了修正。
這樣就可以不用把外部變量(比如類成員)用參數傳給專門的方法(事件處理),可以直接使用這些變量。

static void HandleDemoEvent( object sender, EventArgs e )
{
    Console.WriteLine("Handled by HandleDemoEvent");
}
// C# 1 寫法
EventHandler handler;
handler = new EventHandler(HandleDemoEvent);
handler(null, EventArgs.Empty);

// C# 2 簡寫
handler = HandleDemoEvent;
handler(null, EventArgs.Empty);

// C# 2 匿名方法,直接寫回調方法的實現
String str = "Handled anonymously";
handler = delegate( object sender, EventArgs e )
{
    // 外部變量
    Console.WriteLine( str );
    Console.WriteLine("Handled by HandleDemoEvent");
};
handler(null, EventArgs.Empty);

Action
和delegate差不多的功能,下面一個模擬網絡模塊的類,收到消息後走回調。

public class NetworkManager
{
    Queue<Action<string>> Callbacks;

    public NetworkManager()
    {
        callbacks = new Queue<Action<string>>( );
    }

    public void SendMessage( Action<string> callback )
    {
        Callbacks.Enqueue(callback);
    }

    public void Run( )
    {
        string getData = "這是從網絡得到的消息";

        Action<string> callback = Callbacks.Dequeue();
        callback(getData);
    }
}

class Program
{
    static void Main( string[] args )
    {
        NetworkManager networkMgr = new NetworkManager();

        networkMgr.SendMessage((string data) =>
        {
            Callback(data);
        });

        networkMgr.Run();

        Console.ReadLine();
    }

    static void Callback( string data )
    {
        Console.WriteLine(data);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章