zoukankan      html  css  js  c++  java
  • CLR之委托的揭秘(一)

         初识委托:

             在之前的学习中我们已经可以把对象,值,数组当作参数传递给方法,但是有没有可能把方法也当作参数传递给方法呢?有了这个想法于是就有了委托。方法当作一种参数去传递,但是方法有的有返回值有的没有返回值,这如何处理?委托又用在什么地方?通过这篇文章我们来学习一下委托的用法

            委托解密:

                 在C#中要使用委托。必选先定义要使用的委托,在使用时需要创建该委托的一个或多个实例,以下示例展示了如何声明委托            

    1  /*
    2      委托的安全性非常高,所以在声明委托时,要声明委托返回的类型和参数类型
    3          */
    4     //声明返回类型为double 两个参数类型为long的委托
    5     public delegate double TwolongsOp(long first,long second);
    6     //声明返回类型为string 无参的委托
    7     public delegate string Getstring();
    8     //声明返回类型为void 参数类型为int的委托
    9     public delegate void IntMethodInvoker(int x);
    View Code

             由于定义一个委托实际上是定义一个类,但这个类前面必须加上delegate关键字,所以委托可以定在类中的任何位置,也可以在名称空间中把委托当作顶层对象定义,表面上看,委托声明只需要一句话public delegate double TwolongsOp(long first,long second);,但从CLR角度来看,委托实际上是很复杂的,在使用委托之前先来看一下,底层是如何处理这一句话的。

             编译器在读取这行代码时,实际上会自动为其生成一个完整的类,这个类中包含有一个构造器和Invoke,BeginInvoke,EndInvoke方法。自动生成的这个类继承自MulticastDelegate,所以这个类也继承了MulticastDelegate的字段,属性和方法。这个将在委托链中使用其中的一些方法。

              那么经过CLR的自动编译以后,我们就可以开始使用委托,下面代码就是如何使用委托

     1 class Program
     2     {
     3         //声明返回类型为string 无参的委托
     4         public delegate string Getstring();
     5         static void Main(string[] args)
     6         {
     7             int x = 40;
     8             //实例化委托,并且将int的ToString()方法当作参数传递给委托
     9             Getstring getstring = new Getstring(x.ToString);
    10             //语法糖:简化委托调用和使用new效果一样
    11             Getstring getstring1 = x.ToString;
    12             //调用委托方法
    13             Console.WriteLine(getstring());
    14             //CLR生成的类中就包含的方法安全调用
    15             Console.WriteLine(getstring1.Invoke());
    16         }
    17     }
    View Code

               实际上代码中使用getstring()方法调用和使用Invoke()调用是相同的,因为getstring()方法是委托类型的一个变量,C#编译器会用getstring.Invoke()代替getstring(),如果为了减少输入量,只需要委托示例,就可以只传送地址,这称为委托判断。

              委托链:

             链式语法在C#中非常常见,Linq就是典型的链式方法调用,而委托也支持链式方法调用,委托链指的就是委托对象的集合,利用链式调用集合中的委托所代表的全部方法,但是委托链是有限制和缺点的,委托链中间方法的返回值会被丢弃无法获取,所以委托返回值最好是void,如果是带有返回值的,会返回最后一个方法的返回值。

                举个例子,如果我委托别人帮我去拿一个快递,我又告诉他回来路上顺便帮我带份饭,这是两件事情,如果这两件事都只是去做,不需要拿到返回值,那么委托链可以满足,但是如果我要求两个方法,第一个方法要把快递返回到我手上,第二个方法饭也要返回到我手上,那么就无法获取第一个方法的返回值,也就是说我只能拿到饭,而拿不到快递。接下来看代码比较

     1  //声明返回类型为string 无参的委托
     2         public delegate string Getstring();
     3         static void Main(string[] args)
     4         {
     5             //实例化委托链
     6             Getstring getstatus = null;
     7             //语法糖:支持+=/-=添加方法/移除方法
     8             getstatus += TakeExpress;
     9             getstatus += beltfood;
    10             //获得结果
    11             Console.WriteLine(getstatus());
    12         }
    13         //取快递方法,返回的string当作实体类型看
    14        public static string TakeExpress()
    15         {
    16             return "你的快递是XX,已经为你取了";
    17         }
    18          //带饭方法,返回的string当作实体类型看
    19         public static string beltfood()
    20         {
    21            return "为你带了一份黄焖鸡米饭";
    22         }
    View Code

       

           两个方法最终只输出了最后一个方法的返回值,我们得到了一份黄焖鸡米饭,但是快递没有得到,于是我们修改以下以上代码,改为如下,可以看到两个方法都被执行了

     1  //声明返回类型为string 无参的委托
     2         public delegate void Getstring();
     3         static void Main(string[] args)
     4         {
     5             //实例化委托链
     6             Getstring getstatus = null;
     7             //语法糖:支持+=/-=添加方法/移除方法
     8             getstatus += TakeExpress;
     9             getstatus += beltfood;
    10             //获得结果
    11             getstatus();
    12         }
    13         public static void TakeExpress()
    14         {
    15             Console.WriteLine("你的快递是XX,已经为你取了");
    16         }
    17         public static void beltfood()
    18         {
    19             Console.WriteLine("为你带了一份黄焖鸡米饭");
    20         }
    View Code

     

             匿名委托:

                 匿名方法在.NET 中提高了 代码的可读性和优雅性。对于更多操作较少的方法直接写为匿名函数,这样会大大提高代码的可读性。这里有两个值得注意的地方: 第一,不能使用跳转语句跳转到该匿名方法外,第二 不能使用ref,out修饰的参数,下面是一个匿名委托的调用

       //声明返回类型为string 无参的委托
            public delegate string Getstring(string str);
            static void Main(string[] args)
            {
                 //直接在委托上完善方法
                Getstring Spkeak = delegate (string str)
                {
                    if (str == "哑巴")
                    {
                        return "我是哑巴,我不能说话";
                    }
                    return "我会说话"; 
                };
    
                Console.WriteLine(Spkeak("哑巴"));
    View Code

             小结:

                     委托是一种比较常用的函数回掉方法,常用于某种情况下触发委托。

               

                         

  • 相关阅读:
    函数式编程思想:不变性
    如何制作JQuery Plugin 插件【插件参数的配置】
    jQuery Mobile 中文手册 Ajax开发版——初始化部分
    转载:真实的用户,真实的中国互联网
    创建自定义的jQuery移动主题
    HTML5 LocalStorage 本地存储
    Safari调试工具
    为什么项目经理拿的钱比程序员多?
    移动浏览器项目WebApp需要jQuery吗?移动设备放弃jQuery的理由
    HTML5设计原则
  • 原文地址:https://www.cnblogs.com/Demon-Su/p/7501249.html
Copyright © 2011-2022 走看看