C#知識點講解之C#delegate、event、Action、EventHandler的使用和區別

今天來講一講《C#delegate、event、Action、EventHandler的使用和區別》

小故事講解這四位的前世今生

曾經.Net大佬只有一個Delegete(委託),別人想用委託的時候,必須得用delegate關鍵字來定義一個委託,就像這樣

//定義一個無返回值的,帶一個int參數的委託
public delegate void myDelegate(int num);

話說,委託生來是爲了將方法也作爲參數進行傳遞的。所以後來它學會了發佈者/訂閱者模式。比如:

public myDelegate m_delegate;

m_delegate += MyFun;

public void MyFun(int num)
{
	Debug.Log("my func: " + num);
}


但是它有一個弊端,delegate可以使用“=”將所有已經訂閱的取消(也可以用+/-對訂閱合併和刪除,這是後話,不講),只保留=後新的訂閱,這給了犯罪分子可乘之機。

m_delegate = MyFun1;  //MyFun訂閱被取消,只有MyFun1在訂閱中

public void MyFun1(int num)
{
	Debug.Log("my func1: " + num);
}

所以,event應運而生

event是一種特殊的委託,它只能+=,-=,不能直接用=

public event myDelegate m_event;

m_event += MyFun;
m_event = MyFun;  //錯誤,

通過下面的報錯信息可以看出,event在定義類中(發佈者)是可以直接=的,但是在其他類中(訂閱者)就只能+= -=了,也就是說發佈者發佈一個事件後,訂閱者針對他只能進行自身的訂閱和取消。
在這裏插入圖片描述

但是,在事件發佈和訂閱的過程中,定義事件的原型委託類型常常是一件重複性的工作。

所以,EventHandler應運而生

它的出生就是爲了避免這種重複性工作,並建議儘量使用該類型作爲事件的原型。

//這是它的定義
//@sender: 引發事件的對象
//@e: 傳遞的參數
public delegate void EventHandler(object sender, EventArgs e);

//使用
public event EventHandler m_event;  //修改自定義委託類型爲EventHandler

這時候老大哥delegate說了,你event都有小弟了,我也要有,我每次自定義委託的時候也很麻煩的。

所以,Action應運而生

//Action是系統預定義的一種委託,無返回值,參數在<>中傳入
public Action<int> m_action;

//比較下delegate和Action的定義(個人理解)
public delegate void myDelegate(int num);
public Action<int> m_action;  
//1,Action省略了void,因爲它本身就是無返回值
//2, Action的參數在<>中定義的,delegate就是傳統定義
//3,delegate要用關鍵字,然後自定義一個委託名字。而Action委託名字已定。不需要delegate關鍵字。

知道每個類型因何而來,也就知道了應用場景和區別了,接下來是如何使用了。

使用

    public class Event1 : MonoBehaviour
    {
    	//delegate
        public delegate void myDelegate(int num);
        public myDelegate m_delegate;
        //event
        public event myDelegate m_event;
        //EventHandler
        public event EventHandler m_EventHandle;
        //Action
        public Action<int> m_action;

        void Start()
        {
            m_delegate += MyEventFun;
            m_delegate(1);

            m_delegate = (d) =>{Debug.Log("m_delegate : " + d);};
            m_delegate(2);

            m_event += MyEventFun;
            m_event(3);

			//發佈者中可直接=
            m_event = (d) =>{Debug.Log("m_event : " + d);};
            m_event(4);

            m_EventHandle += MyEventFun;
            m_EventHandle(5, new EventArgs());

            m_EventHandle += (o, e) =>{ Debug.Log("m_EventHandle: " + Convert.ToInt32(o) + "\t " + e.ToString());};
            m_EventHandle(6, new EventArgs());
            m_action += MyEventFun;
            m_action(7);

            m_action = (d) =>{Debug.Log("m_action : " + d);};
            m_action(8);
        }

        public void MyEventFun(int num)
        {
            Debug.Log("my func1: " + num);
        }

        public void MyEventFun(object sender, EventArgs e)
        {
            Debug.Log("my func2: " + Convert.ToInt32(sender) + "\t " + e.ToString());
        }
    }

輸出:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章