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);

结果:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-04-04 10:18  黄厚镇  阅读(3505)  评论(1编辑  收藏  举报