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

由于定义一个委托实际上是定义一个类,但这个类前面必须加上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     }

实际上代码中使用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         }

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

 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         }

匿名委托:

匿名方法在.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("哑巴"));

 小结:

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

                     

时间: 2024-11-09 01:08:36

CLR之委托的揭秘(一)的相关文章

一些写的比较好的的关于委托的资料

看过的一些感觉比较好的关于委托的资料,记录下来 c#委托(delegate)揭秘 C#中delegate的机制原理

C#多线程之旅(1)——介绍和基本概念

原文目录C#多线程之旅(1)——介绍和基本概念 C#多线程之旅目录: C#多线程之旅(1)——介绍和基本概念 C#多线程之旅(2)——创建和开始线程 C#多线程之旅(3)——线程池 C#多线程之旅(4)——同步本质 ...... C#多线程之旅(1)——介绍和基本概念 一.多线程介绍 C#通过多线程支持并行执行的代码.一个线程是一个独立执行的路径,可以同时与其他线程一起运行.一个C#客户端程序(Console,WPF,Winows Forms)开始于一个单独的线程,该线程由CLR和操作系统自动地

C#多线程之旅(1)

阅读目录 一.多线程介绍 二.Join 和Sleep 三.线程怎样工作 四.线程和进程 五.线程的使用和误用 原文地址:C#多线程之旅(1)--介绍和基本概念 C#多线程之旅目录: C#多线程之旅(1)--介绍和基本概念 C#多线程之旅(2)--创建和开始线程 C#多线程之旅(3)--线程池 C#多线程之旅(4)--APM初探 C#多线程之旅(5)--同步机制介绍 C#多线程之旅(6)--详解多线程中的锁 更多文章正在更新中,敬请期待...... C#多线程之旅(1)--介绍和基本概念 回到顶部

[CLR via C#]委托

委托是一种新的面向对象语言特性,委托的功能是在CLR的支持下实现的,这就意味着它并不受限于特定的编程语言,比如C#使用delegate关键字来定义委托,其他的.NET编程语言可以使用自己的方式来定义委托. 以委托作为基础,.NET构造了一个技术大厦,事件驱动.异步调用和Lambda表达式都建立于委托之上,还有许多其他的技术与委托有着密切的联系,掌握委托是探索这些技术领域的前提. 一.委托的简单使用 namespace ConsoleApplication1 { public delegate i

C#综合揭秘——深入分析委托与事件

本篇文章将为你介绍一下 Delegate 的使用方式,逐渐揭开 C# 当中事件(Event)的由来,它能使处理委托类型的过程变得更加简单.还将为您解释委托的协变与逆变,以及如何使用 Delegate 使 Observer(观察者)模式的使用变得更加简单.在事件的介绍上,会讲述事件的使用方式,并以ASP.NET的用户控件为例子,介绍一下自定义事件的使用.最后一节,将介绍Predicate<T>.Action<T>.Func<T,TResult>多种泛型委托的使用和Lamb

读书笔记—CLR via C#委托和attribute

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 委托 类型安全的回调函数,函数签名定义声明.指向静态或实例方法 派生自System.MulticastDelegate的类 将方法绑定到委托时,C#和CLR都允许引用类型的协变性和逆变性 协变性指方法能返回从委托的返回类型派生的类型 逆变性是指

CLR环境中内置了几个常用委托(转)

CLR环境中给我们内置了几个常用委托Action. Action<T>.Func<T>.Predicate<T>,一般我们要用到委托的时候,尽量不要自己再定义一 个委托了,就用系统内置的这几个已经能够满足大部分的需求,且让代码符合规范.一.Action Action封装的方法没有参数也没有返回值,声明原型为: 1 public delegate void Action(); 用法如下: public void Alert() { Console.WriteLine(&q

[转]C#综合揭秘——细说多线程(上)

C#综合揭秘——细说多线程(上) 引言 本文主要从线程的基础用法,CLR线程池当中工作者线程与I/O线程的开发,并行操作PLINQ等多个方面介绍多线程的开发.其中委托的BeginInvoke方法以及回调函数最为常用.而 I/O线程可能容易遭到大家的忽略,其实在开发多线程系统,更应该多留意I/O线程的操作.特别是在ASP.NET开发当中,可能更多人只会留意在客户端使用Ajax或者在服务器端使用UpdatePanel.其实合理使用I/O线程在通讯项目或文件下载时,能尽可能地减少IIS的压力.并行编程

【转】C#综合揭秘——细说多线程(上)

C#综合揭秘——细说多线程(上) 风尘浪子 只要肯努力,梦想总有一天会实现 引言 本文主要从线程的基础用法,CLR线程池当中工作者线程与I/O线程的开发,并行操作PLINQ等多个方面介绍多线程的开发.其中委托的BeginInvoke方法以及回调函数最为常用.而 I/O线程可能容易遭到大家的忽略,其实在开发多线程系统,更应该多留意I/O线程的操作.特别是在ASP.NET开发当中,可能更多人只会留意在客户端 使用Ajax或者在服务器端使用UpdatePanel.其实合理使用I/O线程在通讯项目或文件