zoukankan      html  css  js  c++  java
  • c#之委托详解(Delegate)

    一、委托的概念

    在我们学习委托之前,我们来了解下,什么是委托呢?

    官方概念:委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。

    很多初学者都看不懂官方的概念,一脸懵逼。

    举个例子吧:有几个小伙伴在外面玩,突然有两个人手机忘记带了,并且两个人家距离很近,其中一个人想要骑车回去拿,另一个不想回去,就委托另一个帮他拿。

    其实委托就是一个类型,它所实例化的变量就是委托类型的变量,也可以说委托是一个方法的模板,当我们去掉delegate关键字的时候,就像是一个没有方法体的方法。

    二、委托声明语法

    delegate <return type> <delegate-name> <parameter list>

    三、接下来我们来看下委托三部曲

        public class MyDelegate
        {
            ////1、委托的声明
            public delegate void NoReturnNopara();
            public static void show() 
            {
                //2、委托的实例化
                NoReturnNopara method = new NoReturnNopara(Study);
    
                //3、委托的调用
                method.Invoke();
            }
            public static void Study() 
            {
                Console.WriteLine("正在学习delegate!");
            }
        }

    然后我们调用show方法来看一个结果:

    结果没毛病。

    四、委托的用途

    接下来我们来思考下,这样用委托有什么意义呢?还不如直接 MyDelegate.Study(); 这样。

    当然我们学习委托并不是简单的像上面一样,上面只是为了便于我们学习了解委托而已。接下来我们来看一个打招呼的例子:

    public class MyGreeting
        {
            public static void GreetingChinese(string name) 
            {
                Console.WriteLine("{0},早上好",name);
            }
            public static void GreetingEnglish(string name)
            {
                Console.WriteLine("{0},good morning",name);
            }
        }

    上面是中国人和外国人打招呼的方式,那个问题来了,我们怎么确定打招呼的人是中国人还中外国人呢?简单,我们定义一个枚举然后判断一个不就ok了嘛。

        public class MyGreeting
        {public static void Greeting(string name,PeopleType type) 
            {
                switch (type)
                {
                    case PeopleType.Chinese: Console.WriteLine("{0},早上好", name);
                        break;
                    case PeopleType.English: Console.WriteLine("{0},good morning", name);
                        break;
                }
            }
        }
        public enum PeopleType
        {
            Chinese,
            English
        }

    这种做法满足了我们的需求。但是我们应该有所发现,这个方法的可扩展性很差,日后我们要是又有一个需求,要添加日本人打招呼,韩国人打招呼怎么办?我们就不得不修改枚举和Greeting这个方法内的代码,真是糟糕逶了。

    那么,我们就应该想其它的方法来解决这个问题。从而达到”对扩展开方,对修改封闭“的原则。怎么实现呢?我们可以不管是哪国人,只负责打招呼就好,将打招呼的逻辑做为参数。

    首先,我们先定义一个打招呼的委托。

     public delegate void DeleGreeting(string name);

    然后将这个委托做为参数传给 Greeting(string name,DeleGreeting greeting)  这个方法,让这个方法来调用打招呼。

            public static void Greeting(string name,DeleGreeting greeting) 
            {
                greeting.Invoke(name);
            }

    最后,我们来实例化这个委托,并调用这个方法。

            static void Main(string[] args)
            {
                DeleGreeting method = new DeleGreeting(MyGreeting.GreetingChinese);
                MyGreeting.Greeting("张三",method);
    
                DeleGreeting method1 = new DeleGreeting(MyGreeting.GreetingEnglish);
                MyGreeting.Greeting("lucy", method1);
    
                Console.Read();
            }

    结果如下:

    用这种方式实现的话,以后不管你添加多少种国家的打招呼。都不用去改动 Greeting(); 这个方法,只需要扩展一个打招呼的方法就行了。达到”对扩展开方,对修改封闭“的原则。

    五、多播委托

    接下来我们来看一下什么是多播委托

    委托对象可使用 "+" 运算符进行合并。一个合并委托调用它所合并的两个委托。只有相同类型的委托可被合并。"-" 运算符可用于从合并的委托中移除组件委托。

    也就是说,可以将多个方法绑定给同一个委托

                DeleGreeting method = new DeleGreeting(MyGreeting.GreetingChinese);
                method += new DeleGreeting(MyGreeting.GreetingEnglish);
                MyGreeting.Greeting("李四", method);

    结果:

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Java HashMap存储问题
    <转>堆和栈的区别
    Linux shell命令
    DNS(三)DNS SEC(域名系统安全扩展)
    DNS (二)协议
    绕过CDN查找网站真实IP方法
    stream流思想应用
    http接口实现附件对接
    AQS深入分析
    AQS快速入门
  • 原文地址:https://www.cnblogs.com/hhzblogs/p/7837213.html
Copyright © 2011-2022 走看看