天天看点

委托与事件 Delegate Event浅显理解

委托像是一个承包商,你有什么活儿,我可以帮你做(通知你做),但你的活儿我得能做(我有能力通知).

我是一个承包商,我可以帮人代办明天6点钟的事宜(这个只是个例子,关键是我能够监听一个时机,时机触发的时候,我就会执行 收听者委托在我这里的回调.)

比如AAA想在明天6点时,起床

BBB想在明天 6点时 跑步

CC想在 明天6点时 吃饭

那AAA BBB CCC 都可以 把自己的事委托给我.等到第二天6点, 我就会调起 AAA的 起床,BBB的跑步,CCC的吃饭.

再比如一场战斗即将打响,可士兵不知道啥时候打响,都得听一个指令

AAA 在打响的时候 带领队伍冲啊

BBB 在打响的时候 负责掩护

CCC 在打响的时候 负责包抄

那AAA BBB CCC 都可以把各自的事,注册到 冲锋号(按键 C), 当冲锋号一响,大家就各自行动.

event 的规则是 只能出现在 -= 或 +=的左边, 而不能使用= ,这样就避免了 ,其它收听者把监听者已经注册的回调给覆盖掉.

以上就是我对 委托 事件浅显理解希望可以帮助到刚接触这部分知识的童鞋, 当然也有许多不足之处,欢迎指正,讨论.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace TestDele
{
  public  interface Charge
    {
        void ChargeForward();
    }


    class AAA : Charge
    {
        List<Charge> teams;
        public AAA()
        {
            TestDelegl.fightingBegan += LeadInTeam;
            TestDelegl.fightingBegan += ChargeForward;//在合适的时机,我有个事要做,可我没工夫去等这个时机,我把这个事委托给你(观察者),等时机到了,你帮我把事办了.
        }
        public void ChargeForward()
        {
            Debug.Log(GetType().Name + ":冲啊");
        }
        public void LeadInTeam()
        {
            Debug.Log(GetType().Name + ":大家都跟在我后面");
        }
    }

    class BBB : Charge
    {
        public BBB()
        {
            TestDelegl.fightingBegan += ChargeForward;//在合适的时机,我有个事要做,可我没工夫去等这个时机,我把这个事委托给你(观察者),等时机到了,你帮我把事办了.
        }
        public void ChargeForward()
        {
            Debug.Log(GetType().Name + ":我来掩护");
        }

        
    }

  public  class CCC : Charge
    {
        public CCC()
        {
            TestDelegl.fightingBegan += ChargeForward;//在合适的时机,我有个事要做,可我没工夫去等这个时机,我把这个事委托给你(观察者),等时机到了,你帮我把事办了.
        }
        public void ChargeForward()
        {
            Debug.Log(GetType().Name + ":我来包抄");
        }
       
        //TestDelegl testDelegl;
        //void TestAdd()
        //{
        //    testDelegl.fightingBegan += ChargeForward;
        //}
    }


    public delegate void FightingBegan();
    public class TestDelegl : MonoBehaviour
    {
        public static event FightingBegan fightingBegan;  //event不能使用=号,保证了其安全性,如果是委托,外界使用=号,就直接覆盖了,之前添加的回调,都会失去.
        
        void Start()
        {
           
           fightingBegan += TestCre;
            AAA aaa = new AAA();
            BBB bbb = new BBB();
            CCC ccc = new CCC();
        }
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.C))
            {
                fightingBegan();//当事件发生时,观察者执行收听者已经注册好的委托
            }
        }

        void TestCre()
        {
            Debug.Log(GetType().Name + ":哭啼啼");
        }
    }
}
           
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using TestDele;
public class TestDeleglAAA : MonoBehaviour,Charge
{
    public void ChargeForward()
    {
        Debug.Log(GetType().Name+":冲啊~~~~~~~~~~");
    }

    void Start()
    {

            TestDelegl.fightingBegan += ChargeForward;//把委托商请过来,我要给你注册个方法   
    }


}

           
委托与事件 Delegate Event浅显理解

关于 event事件注册与删除容易掉的坑

项目中通常会给 event注册不少事件, 但有时候却要删除部分事件,现在就来说说注册和删除事件注意的问题

namespace EventTest
{
    delegate void MyDel();//声明委托类型,无参无返回值
    class Program
    {
        static void Main(string[] args)
        {
            new AAA();//实例1个AAA
            new BBB();//实例第1个BBB
            new BBB();//实例第2个BBB
            new BBB();//实例第3个BBB
            new CCC();//执行事件
        }
    }

    class CCC
    {
        public static event MyDel EventPrin;
        public CCC()
        {
            EventPrin();
        }
    }
    class AAA
    {
        public AAA()
        {
            CCC.EventPrin += ABC;//注册一个名称为ABC的方法
            
        }
        void ABC()
        {
            Console.WriteLine("aaa");
        }
    }
    class BBB
    {
        public BBB()

        {
           
            CCC.EventPrin -= ABC;//删除一个名称为ABC的方法
            CCC.EventPrin += ABC;//注册一个名称为ABC的方法
        }
        void ABC()
        {
            Console.WriteLine("bbb");
        }
    }
}
           
委托与事件 Delegate Event浅显理解

由此可看出 CCC.EventPrin -= ABC; 无法删除名为ABC的方法!! 为什么呢?? 我的判断是,它要删除的是,当前对象里的名为ABC的方法, 如果有其它对象中的ABC方法也注册了, 在本类里面去按名称删除,是做不到的.