104-13-委托与事件用法的对比

本文通过对比分析和鸿门宴的故事,详细解释了委托和事件在C#中的相似点和不同点,强调了事件在防止意外清除已关联方法上的保护作用。并以代码示例展示了委托可能导致的内奸问题,而事件则能有效避免此类问题,确保程序的稳定性。
摘要由CSDN通过智能技术生成

1. 相同点

事件对象本质就是一个私有的委托对象,以及共有的两个方法add和Remove

2. 不同点

  1. 委托变量与实现方法的关联允许使用Null ,这样会对之前的关联产生影响
  2. 事件变量与实现方法的关联不允许使用Null,而且正常的赋值不会影响之前已经存在的关联关系,这样的话,避免用户将对象事件清除,起到保护作用
  3. 对委托与事件的理解,
    委托是 Windows服务器系统
    事件则是Windows 普通用户系统

3.一个故事

通过讲述一个 鸿门宴的故事,更好的理解委托与事件的关系

 鸿门宴的故事:
        1. 冷知识:项羽帐下五员大将:龙且A、季布B、钟离昧C、英布D、虞子期E
           在demo中人员名字用ABCDE代表
        2. 背景:项羽请刘备吃饭,顺便借机弄死他
        3. 于是做了如下安排:
           项羽敬酒的时候,
           1. 如果项羽用左手敬酒:龙且 过来砍死刘备
           2. 如果项羽用右手敬酒:季布 过来砍死刘备
           3. 如果项羽直接将酒杯摔在地上:龙且、季布、钟离昧、英布、虞子期一起来砍死刘备
        
        用代码实现上面的过程,
        结论就是:
        如果用委托的话,可能会出来内奸
        因为在委托变量与实现方法进行关联的时候,会影响到已经关联的方法
        如果用事件的话,则不会
        注:上面的背景纯粹是为了便于理解,杠精请绕道
3.1 用委托实现
    #region 主函数调用           
    XiangYu xiangYu = new XiangYu();
    A a = new A(xiangYu);
    B b = new B(xiangYu);
    C c = new C(xiangYu);
    xiangYu.JuShouMethod("左手");
    Console.ReadLine();
    Console.WriteLine("又宴请了刘邦");
    xiangYu.JuShouMethod("右手");
    Console.ReadLine();
    #endregion  




  #region 用委托实现
    //【1】创建委托
    public delegate void JuShou(string hands);
    public class XiangYu
    {

        public void JuShouMethod(string hands)
        {
            Console.WriteLine($"大王举起了{hands}手!");
            //【5】调用委托变量,实现委托
            if (JuShowVar != null)
            {
                JuShowVar(hands);
            }
            else
            {
                Console.Beep();
                Console.WriteLine("项羽阵营中出现了叛徒!");
            }

        }
        //【3】根据委托定义委托变量
        public JuShou JuShowVar;

    }

    public class A
    {
        public A(XiangYu xiangYu)
        {
            //【4】将创建的方法赋值给声明的变量
            // 这个关联方法一定要用+=,否则会将之前的关联方法替换掉,这也是不要用委托的原因之一
            xiangYu.JuShowVar += new JuShou(this.CutLiubang);
        }
        //【2】根据委托创建实现方法
        private void CutLiubang(string hands)
        {
            if (hands.Equals("左手"))
            {
                Console.WriteLine($"我是龙且,大王举起了{hands}手,我要砍死刘邦");
            }
        }
    }
    public class B
    {
        public B(XiangYu xiangYu)
        {
            //【4】将创建的方法赋值给声明的变量
            // 这个关联方法一定要用+=,否则会将之前的关联方法替换掉,这也是不要用委托的原因之一
            xiangYu.JuShowVar += this.CutLiubang;
        }
        private void CutLiubang(string hands)
        {
            if (hands.Equals("右手"))
            {
                Console.WriteLine($"我是季布,大王举起了{hands}手,我要砍死刘邦");
            }
        }

    }
    public class C
    {
        public C(XiangYu xiangYu)
        {
            //【4】将创建的方法赋值给声明的变量
            // 这里设置为Null,会将之前的关联全部处理掉
            xiangYu.JuShowVar = null;
        }
    }
    #endregion


3.2 用事件实现
 #region 主函数调用           
    XiangYu xiangYu = new XiangYu();
    A a = new A(xiangYu);
    B b = new B(xiangYu);
    C c = new C(xiangYu);
    xiangYu.JuShouMethod("左手");
    Console.ReadLine();
    Console.WriteLine("又宴请了刘邦");
    xiangYu.JuShouMethod("右手");
    Console.ReadLine();
    #endregion  


 #region 用事件实现
    //【1】创建委托
    public delegate void JuShou(string hands);
    public class XiangYu
    {
        //【2】创建事件
        public event JuShou jushouEvent;

        public void JuShouMethod(string hands)
        {
            Console.WriteLine($"大王举起了{hands}手!");
            //【3】激活事件
            if (jushouEvent != null)
            {
                jushouEvent(hands);
            }
            else
            {
                Console.Beep();
                Console.WriteLine("项羽阵营中出现了叛徒!");
            }
        }
    }

    public class A
    {
        public A(XiangYu xiangYu)
        {
            //【4】将事件关联方法
            // 事件关联方法:事件无法直接从外部赋值,这样的话,避免用户将对象事件清除,起到保护作用
            xiangYu.jushouEvent += new JuShou(this.CutLiubang);
            //xiangYu.jushouEvent += null;     //这样设置会报错
            //xiangYu.jushouEvent -= new JuShou(this.CutLiubang);//这样不会影响之前的关联

        }
        //【5】创建事件响应方法
        private void CutLiubang(string hands)
        {
            if (hands.Equals("左手"))
            {
                Console.WriteLine($"我是龙且,大王举起了{hands}手,我要砍死刘邦");
            }
        }
    }
    public class B
    {
        public B(XiangYu xiangYu)
        {
            //【4】将事件关联方法
            // 事件关联方法:事件无法直接从外部赋值,这样的话,避免用户将对象事件清除,起到保护作用
            xiangYu.jushouEvent += this.CutLiubang;
        }
        private void CutLiubang(string hands)
        {
            if (hands.Equals("右手"))
            {
                Console.WriteLine($"我是季布,大王举起了{hands}手,我要砍死刘邦");
            }
        }

    }
    public class C
    {
        public C(XiangYu xiangYu)
        {
            //【4】将事件关联方法
            // 事件关联方法:事件无法直接从外部赋值,这样的话,避免用户将对象事件清除,起到保护作用
            //xiangYu.jushouEvent = null; //这样设置会报错
        }
    }

    #endregion
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烂笔头技术栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值