CLR之委托的揭秘(一)

     初识委托:数组

         在以前的学习中咱们已经能够把对象,值,数组看成参数传递给方法,可是有没有可能把方法也看成参数传递给方法呢?有了这个想法因而就有了委托。方法看成一种参数去传递,可是方法有的有返回值有的没有返回值,这如何处理?委托又用在什么地方?经过这篇文章咱们来学习一下委托的用法
安全

        委托解密:ide

             在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的字段,属性和方法。这个将在委托链中使用其中的一些方法。spa

          那么通过CLR的自动编译之后,咱们就能够开始使用委托,下面代码就是如何使用委托code

 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(),若是为了减小输入量,只须要委托示例,就能够只传送地址,这称为委托判断。对象

          委托链:blog

         链式语法在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

 

         小结:

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

相关文章
相关标签/搜索