初识C#事件

229 阅读3分钟
  • 本文已参加「新人创作礼活动」,一起开启掘金之路。

一 事件

在这里插入图片描述

1 抛砖引玉·案例

  • 订阅和发布机制
    • 比如说,我要下楼去吃饭,正常情况下我会问一下室友是否需要我带饭。我每个人问一遍的情况,很浪费时间。
    • 现在,我提前放好纸和笔,要求别人列好需要我帮忙的事情,我到时候直接拿着单子下楼。这就是订阅和发布机制。

1.1工具人下楼案例

1.1.1 ToolMan.cs

 public delegate void DownStairDelegate();
    public class ToolMan
    {
        public string Name { get; set; }
        //事件--受限制的委托--event本质上还是委托
        //限制一:只能出现在+=、-=的左侧
        //限制二:只能在内部调用
        public DownStairDelegate DoList = null;

        public ToolMan(string name)
        {
            Name = name;
        }

        public void DownStair()
        {
            Console.WriteLine("工具人"+Name+"下楼了");
            if (DoList != null)
            {
                DoList();
            }
        }
    }

1.1.2 LazyMan.cs

using System;

namespace test06
{
    public class LazyMan
    {
        public string Name { get; set; }

        public LazyMan(string name)
        {
            Name = name;
        }

        public void TakeFood()
        {
            Console.WriteLine("给"+Name+"外卖");
        }

        public void TakePackage()
        {
            Console.WriteLine("给"+Name+"快递");
        }
    }
}

1.1.3 Program.cs

using System;

namespace test06
{
    internal class Program
    {
        //工具人下楼案例
        public static void Main(string[] args)
        {
            var toolMan = new ToolMan("小明");
            var lazyMan = new LazyMan("小李");
            var lazyMan1 = new LazyMan("小王");
            var lazyMan2 = new LazyMan("小空");
            //注意 +=:添加委托 
            toolMan.DoList += lazyMan.TakeFood;
            toolMan.DoList += lazyMan1.TakePackage;
            toolMan.DoList += lazyMan2.TakeFood;
            toolMan.DoList();
            Console.WriteLine("===========");
            toolMan.DoList -= lazyMan2.TakeFood;//取消了小空的拿外卖的委托。
            toolMan.DoList();
            //=:覆盖之前的所有委托【但委托的总数变为1】
            Console.WriteLine("===========");
            toolMan.DoList = lazyMan2.TakeFood;
            toolMan.DoList();
            
            //工具人并准备没有下楼,但消息已经发布出去了
            //意思就是消息只有发布者去发布,其他人无权发布,只能订阅这些消息--不适合外部调用
            //解决
            //toolMan.DoList();
        }
    }
}

1.1.4 测试结果

在这里插入图片描述

1.1.5 升级到事件

在这里插入图片描述

 internal class Program
    {
        //工具人下楼案例
        public static void Main(string[] args)
        {
            var toolMan = new ToolMan("小明");
            var lazyMan = new LazyMan("小李");
            var lazyMan1 = new LazyMan("小王");
            var lazyMan2 = new LazyMan("小空");
            //注意 +=:添加委托 
            toolMan.DoList += lazyMan.TakeFood;
            toolMan.DoList += lazyMan1.TakePackage;
            toolMan.DoList += lazyMan2.TakeFood;
            //toolMan.DoList();
            Console.WriteLine("===========");
            toolMan.DoList -= lazyMan2.TakeFood;//取消了小空的拿外卖的委托。
            //toolMan.DoList();
            //=:覆盖之前的所有委托【但委托的总数变为1】
            Console.WriteLine("===========");
            //toolMan.DoList = lazyMan2.TakeFood;
            //toolMan.DoList();
            
            //工具人并准备没有下楼,但消息已经发布出去了
            //意思就是消息只有发布者去发布,其他人无权发布,只能订阅这些消息--不适合外部调用
            //解决
            //toolMan.DoList();
            //事件情况下只有发布者发布了消息,才会执行委托
            toolMan.DownStair();
        }
    }

在这里插入图片描述

二 委托和事件的区别和联系

在这里插入图片描述

  • 事件是一种特殊的委托,或者说是受限制的委托,是委托一种特殊应用,只能施加+-,-二操作符。二者本质上是一个东西。
  • event ActionHandler Tick;//编译成创建一个私有的委托示例,和施加在其上的add,remove方法.
  • event只允许用add,remove方法来操作,这导致了它不允许在类的外部被直接触发,只能在类的内部适合的时机触发。委托可以在外部被触发,但是别这么用。
  • 使用中,委托常用来表达回调,事件表达外发的接口。
  • 委托和事件支持静态方法和成员方法,delegate(void* pthis,f_ptr)支持静态返回方法时,pthis传null.支持成员方法时pthis传被通知的对象.
  • 委托对象里的三个重要字段是,pthis、f_ptr、pnext,也就是被通知对象引用,函数指针\地址,委托链表的下一个委托节点。