zoukankan      html  css  js  c++  java
  • 一眼就能看懂的C#委托、多播委托和事件的区别与联系。

    先说结论

    委托:

    1.一种可以把函数名当参数传递的类型

    2.可以通过delegateName()直接触发

    3. 可以赋值。

    多播委托:

    1可以传递多个函数名,调用时会运行多个函数

    2.可以通过delegateName()直接触发

    3.可以赋值。

    事件:

    1.类似多播委托,本质更像是委托的一个实例,但是具有封装性。

    2.不能像委托一样直接触发,只能通过事件相关函数触发。

    3.不像委托一样可以直接赋值,但是可以通过+= 和 -=增加和移除函数。

    4.可以实现发布订阅者模式。

    委托实例(标粗注意):

    我们希望给委托加一个事件,一个中国人问好,并且触发委托

    class Program
        {
            public delegate void SayDelegate(string name);
            public class ChinesePeople
            {
                public void SayChinese(string name)
                {
                    Console.WriteLine("你好" + name);
                }
                public void Greet(string name, SayDelegate action)
                {
                    action(name);
                }
            }
            static void Main(string[] args)
            {
                string name = "张三";
                ChinesePeople cp = new ChinesePeople();
           //给委托赋值 SayDelegate delegate1
    = cp.SayChinese;
           //只传一个函数名时,两种写法都可以
           delegate1(name); cp.Greet(name,delegate1); cp.Greet(name,cp.SayChinese);
            Console.ReadKey(); } }

    结果:

    你好张三
    你好张三
    你好张三


    多播委托实例一:

    我们希望委托让一个中国人和一个英国人问好,这时候我们通过+=添加函数。

    public delegate void SayDelegate2(string name);
     
        public class ChinesePeople
        {
            public void SayChinese(string name)
            {
                Console.WriteLine("你好" + name);
            }  
        }
        public class EnglishPeople
        { 
            public void SayEnglish(string name)
            {
                Console.WriteLine("hello" + name);
            }
            
        }
       
        class Program
        {
            static void Main(string[] args)
            {
                string name = "张三";
                ChinesePeople cp = new ChinesePeople();
                EnglishPeople ep = new EnglishPeople(); 
                SayDelegate2 delegate1 = cp.SayChinese;
                delegate1 += ep.SayEnglish;
                delegate1(name); 
                Console.ReadLine();
            }
        }

    结果:

    你好张三
    hello张三

    多播委托实例二:

    delegate1(name)看起来太简洁了,我们根本不知道这个委托是要干什么的, 如果我们跟第一个一样,把委托封装到一个方法里调用呢?这样我们就知道这个委托负责做什么的啦

        public delegate void SayDelegate(string name);
    
        public class ChinesePeople
        {
            public void SayChinese(string name)
            {
                Console.WriteLine("你好" + name);
            }  
        }
        public class EnglishPeople
        { 
            public void SayEnglish(string name)
            {
                Console.WriteLine("hello" + name);
            }
            
        }
        public class GreetEvent
        {
            public void Greet(string name, SayDelegate2 action)
            {
                action(name);
            }
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                string name = "a";
                ChinesePeople cp = new ChinesePeople();
                EnglishPeople ep = new EnglishPeople(); 
                GreetEvent gEvent= new GreetEvent();
                SayDelegate delegate1 = cp.SayChinese;
                delegate1 += ep.SayEnglish;
           //这样我们就知道这是在“Greet”问好 gEvent.Greet(name, delegate1); Console.ReadLine(); } }

    写完我们发现,wow竟然需要这么多声明?这完全不符合我们面向对象封装性的原则呀!我们能不能把委托、事件写到一起呢?

    于是事件(Event)出来了。

    事件实例:

    模拟情景:主人来了,主人问好之后,两个客人——一个中国人一个英国人也向主人问好。

    (这就是经典的发布订阅模式,发布者是主人,订阅者是中国人和英国人。发布者做出的行动之后,订阅者也做出相应的行为)

    所以我们新建一个主人类,封装委托,事件,和触发事件的函数。

      public class Master
        {
            public delegate void SayDelegate(string name);
            public event SayDelegate SayEvent;
            public void Greet(string name)
            {
                if (SayEvent != null)
                {
                    SayEvent(name);
                }
            }
        }
        
        public class ChinesePeople
        {
            public void SayChinese(string name)
            {
                Console.WriteLine("你好" + name);
            }  
        }
        public class EnglishPeople
        { 
            public void SayEnglish(string name)
            {
                Console.WriteLine("hello" + name);
            }
            
        } 
        class Program
        {
            static void Main(string[] args)
            {
                string name = "张三";
                ChinesePeople cp = new ChinesePeople();
                EnglishPeople ep = new EnglishPeople(); 
                Master m = new Master();
              
                m.SayEvent += cp.SayChinese;
                m.SayEvent += ep.SayEnglish;
                m.SayEvent -= ep.SayEnglish;
                m.Greet(name);
    
                Console.ReadLine();
            }
        }

    注意点:1. 事件不能像委托直接delegate(name)调用,也就是说m.SayEvent()是不可行的。只能通过调用函数去触发事件

        2.事件不能直接赋值,只能通过+=和-=增加和移除函数

    突然写这个文章是因为工作中遇到的需要传函数名进行封装的方法~记录一下,也希望能给初学者带来帮助。

  • 相关阅读:
    5R(康奈尔)笔记法
    【软件】MyEclipse 显示行数及Eclipse修改字体
    Linux运维工程师必备的十个技能点
    centos下部署LAMP环境(Linux+Apache+mysql+php)(转载文章:https://www.cnblogs.com/apro-abra/p/4862285.html)
    MySQL之show命令 (转载https://www.cnblogs.com/andy6/p/6171945.html)
    MySQL安装完成后重置密码
    MySQL面试题
    mysql运维必备知识点(转载至其他作者)
    centos 7 下安装部署mysql 5.7
    Linux服务部署之NTP时间服务器
  • 原文地址:https://www.cnblogs.com/babydoll/p/10722410.html
Copyright © 2011-2022 走看看