前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >委托与事件-委托详解(一)

委托与事件-委托详解(一)

作者头像
小世界的野孩子
发布2019-07-30 18:34:00
1.1K0
发布2019-07-30 18:34:00
举报

前言

  说起委托和事件,我就想起了再学校的时候,当时死记硬背去记什么是委托什么是事件。记得当时蝼某人问我,委托是什么?但是只知道一点点,就跟他说:打个比方,我要喝水,但是我不去买,我委托你去帮我买水。这就是委托,够直白简单了吧。

委托语法使用

  语法: public delegate void BuyWaterEventHandler();

  其中 delegate 是关键字,声明委托的时候命名时后缀加入EventHandle

  这就是一个简单的委托,就是这么简单。我们相对于平时使用的方法有什么区别吧

  方法:

        public static string BuyWaterSlef()
        {
            return "自己去买水";
        }

  我们看方法,是实现买水这个功能的,而委托是委托你去帮我买水的。方法是具体做事实现功能,委托只是命令而已。

  我们具体使用委托来实现刚刚那个委托蝼某人去买水的程序设计。

    /// <summary>
    /// 蝼某人去买水的类
    /// </summary>
    public class LouBuy
    {
        /// <summary>
        /// 蝼某人买水的方法
        /// </summary>
        /// <returns></returns>
        public static string LouBuyWater()
        {
            return "蝼某人去买水";
        }
    }


    /// <summary>
    /// 定义买水的委托
    /// </summary>
    /// <returns></returns>
    public delegate string BuyWater();

 
    /// <summary>
    /// 买水委托实现的类
    /// </summary>
    public class MainBuy
    {
        /// <summary>
        /// 实现委托
        /// </summary>
        /// <returns></returns>
        public static string BuyFun()
        {
            /// 委托中加入蝼某人的方法
            BuyWater buyWater = new BuyWater(LouBuy.LouBuyWater);
            ///返回结果
            return  buyWater();
        }     

    }

  最后这里输出的是”蝼某人去买水”

  BuyWater buyWater = new BuyWater(LouBuy.LouBuyWater);

  这里声明委托方法,BuyWater委托中加入LouBuy.LouBuyWater买水的方法,这个方法参数必须加入,因为委托的构造函数参数不为空。同时需要注意委托参数的返回类型都是要和具体委托方法一样的。

  在这个例子中都是返回的string,都是无参数的

委托链(多播委托)

  上面我们简单的介绍了下委托及其用法,这里我们可以了解一下委托链,顾名思义,委托链也就是委托连续,啥意思呢?继续上面的例子,我委托蝼某人去买水,然后顺带买包辣条。

    /// <summary>
    /// 蝼某人去买水的类
    /// </summary>
    public class LouBuy
    {
        /// <summary>
        /// 蝼某人买水的方法
        /// </summary>
        /// <returns></returns>
        public static void LouBuyWater()
        {
             Console.WriteLine ("蝼某人去买水";)
        }

        /// <summary>
        /// 楼某人买辣条方法
        /// </summary>
        /// <returns></returns>
        public static void LouBuyLT()
        {
            Console.WriteLine ("楼某人又买了辣条";)
        }
    }

 
    /// <summary>
    /// 定义买水的委托
    /// </summary>
    /// <returns></returns>
    public delegate void BuyWater();

 
    /// <summary>
    /// 买水委托实现的类
    /// </summary>
    public class MainBuy
    {
        /// <summary>
        /// 实现委托
        /// </summary>
        /// <returns></returns>
        public static void BuyFun()
        {
            /// 委托中加入蝼某人的方法
            BuyWater buyWater = new BuyWater(LouBuy.LouBuyWater);
            buyWater += LouBuy.LouBuyLT;
            ///返回结果
             Console.WriteLine (buyWater();)
        }      

    }

  这里就相当于我委托蝼某人做了两件事情,先去买水然后顺带买了辣条,委托链(多播委托)可以使用+=来增加委托中调用的方法,同理也可使用-=来删除委托中调用的方法.

  注意,委托链(多播委托)--委托的签名必须返回void,否则就只能得到委托调用的最后一个方法的结果。同时委托链(多播委托)中注意不要调用一些必须有特定顺序的方法,因为委托中调用其方法链的顺序并未正式定义。

  委托链(多播委托)还可能出现一个非常严重的问题,也就是在委托中多个方法调用时,一旦出现了异常报错,则整个迭代都会停止。

    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }

        static void Two()
        {
            Console.WriteLine("two");
        }

 
        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            try
            {
                actionMain();
            }
            catch (Exception)
            {

                Console.WriteLine("异常报错");

            }
        }
 

    }
    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }

        static void Two()
        {
            Console.WriteLine("two");
        }

 
        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            try
            {
                actionMain();
            }
            catch (Exception)
            {

                Console.WriteLine("异常报错");

            }
        }
 

    }
    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }

        static void Two()
        {
            Console.WriteLine("two");
        }

 
        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            try
            {
                actionMain();
            }
            catch (Exception)
            {

                Console.WriteLine("异常报错");

            }
        }
 

    }
    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }

        static void Two()
        {
            Console.WriteLine("two");
        }

 
        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            try
            {
                actionMain();
            }
            catch (Exception)
            {

                Console.WriteLine("异常报错");

            }
        }
 

    }
    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }

        static void Two()
        {
            Console.WriteLine("two");
        }

 
        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            try
            {
                actionMain();
            }
            catch (Exception)
            {

                Console.WriteLine("异常报错");

            }
        }
 

    }

  在这个委托调用中,遇到抛出异常错误时就会停止迭代。最终返回结果为

one

抛出异常报错

扩展延伸

  一、解决多播委托问题

  上面讲到多播委托中一个调用抛出异常,整个迭代都会停止。下面讲解一个解决此问题的方法。在Delegate类中定义了GetInvocationList()方法,它返回的是Delegate对象数组,现在可以使用这个委托调用与委托直接相关的方法,捕获异常,并继续下一次迭代。

    class Pragram
    {
        static void One()
        {
            Console.WriteLine("one");
            throw new Exception("抛出异常报错");
        }
        static void Two()
        {
            Console.WriteLine("two");
        }

        public delegate void ActionMain();
        static void Main()
        {
            ActionMain actionMain = One;
            actionMain += Two;
            Delegate[] delegates = actionMain.GetInvocationList();
            foreach (ActionMain item in delegates)
            {
                try
                {
                    item();
                }
                catch (Exception)
                {
 
                    Console.WriteLine("抛出异常");
                }
            }
        }

    }

  再看我们对出现问题的代码进行修改,这里抛出异常之后会继续迭代,并不会停止,返回的结果是

one

抛出异常错误

Two

二、委托其他写法(Action<T>委托和Fun<T>委托)

  我们上面介绍到委托

public delegate void BuyWater(string a);

BuyWater buyWater = new BuyWater(LouBuy.LouBuyWater);

  下面我们介绍另外两种委托形式,Action<T>委托和Fun<T>委托

  Action<T>委托表示引用一个void返回类型的方法,可以没有参数,也可以有很多参数,一个参数Action<in T>,l两个参数Action<in T1,in T2>

Action<string> action=LouBuy.LouBuyWater;

  Fun<T>委托表示可以调用允许带返回类型的参数,Fun<out TResult>表示委托类型可以调用带返回类型且无参数的方法,Fun<in T,out TResult>调用带返回类型带参数的方法

Func<string, string> buyWater = LouBuy.LouBuyWater;//表示返回string类型,参数也是string类型的一个方法

总结

  以前总在说委托与事件,都没有一次去了解熟悉它,现在得好好巩固一下了。到这里就介绍完了委托,看上去也挺简单的。我们下一节继续看Event事件。然后结合委托一起看看委托加事件如何运用的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 委托语法使用
  • 委托链(多播委托)
  • 扩展延伸
    •   一、解决多播委托问题
      • 二、委托其他写法(Action<T>委托和Fun<T>委托)
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档