委托是C#中最为常见的内容。与类、枚举、结构、接口一样,委托也是一种类型。类是对象的抽象,而委托则可以看成是函数的抽象。一个委托代表了具有相同参数列表和返回值的所有函数。比如:

  1. delegate int GetCalculatedValueDelegate(int x, int y);

在上面的定义中,我们定义了一个委托,这个委托代表着一类函数,这些函数的第一个参数是整数型的x,第二个参数是整数型的y,而函数的返回值则是一个整数。在这里,为了描述方便,我们把这一类的函数称为具有相同签名(signature)的函数(注意:这个签名并不是数字签名中的概念,而只是表示这类函数具有相同的参数列表和返回值)。

既然委托是一种类型,那么它就能被用来定义参数、变量以及返回值。由委托定义的变量用于保存具有相同签名的函数实体。需要注意的是,C#和C++不同,C++中的函数指针只能保存全局的或者静态的函数,而C#中的委托实体则可以指代任何函数。

现在我们来看一个例子,在这个例子中,我们使用了上面定义的那个委托,并创建了一个委托实体,使其指代程序中的AddCalculator函数,接下来就可以直接像使用函数本身一样,使用这个委托实体来获得计算的结果。

  1. delegate int GetCalculatedValueDelegate(int x, int y);   //声明一个委托。委托代表了具有相同参数列表和返回值的所有函数。
  2. static int AddCalculator(int x, int y)
  3. {
  4. return x + y;
  5. }
  6. static int SubCalculator(int x, int y)
  7. {
  8. return x - y;
  9. }
  10. static void Main(string[] args)
  11. {
  12. GetCalculatedValueDelegate d = AddCalculator;   //实例化
  13. 或: //GetCalculatedValueDelegate d=new GetCalculatedDelegate(AddCalculator);
  14. Console.WriteLine(d(10, 20));   //调用
  15. }

到这里也就能基本上明白“委托”的意义了,针对上面的Main函数,本来需要调用AddCalculator函数的,却通过d来调用了,也就是,后续对AddCalculator的操作由d代为效劳。本来是要小明去老师办公室拿粉笔盒的,由于小明和小文是好朋友,因此小明就要小文代他去拿,于是小文成了小明的代理,小明委托小文去拿粉笔盒。

现在我们来考虑委托作为参数的情形。将委托作为参数,可以把函数本身的处理逻辑抽象出来,而让调用者决定最终使用什么样的逻辑去处理。请看下面的例子:

  1. delegate int GetCalculatedValueDelegate(int x, int y);
  2. static int AddCalculator(int x, int y)
  3. {
  4. return x + y;
  5. }
  6. static int SubCalculator(int x, int y)
  7. {
  8. return x - y;
  9. }
  10. static int Calculator(GetCalculatedValueDelegate del, int x, int y)
  11. {
  12. return del(x, y);
  13. }
  14. static void Main(string[] args)
  15. {
  16. int result=Calculator(AddCalculator, 10, 20);   //Calculator说:我不知道10,20之间怎么运算,我委托给AddCalculator来处理;
  17. Console.WriteLine(result);
  18. }

在上面的例子中,Calculator函数的第一个参数就是一个委托。事实上,Calculator对x和y将会做什么处理,它本身并不知道,如何处理x和y由GetCalculatedValueDelegate来决定。那么在Main方法里,我们将AddCalculator方法作为参数传递给Calculator,表示让Calculator用AddCalculator的逻辑去处理x和y。这也很形象:Calculator说:“我不知道要怎么处理x和y,让del去处理好了!”于是就把x和y扔给了del。

这种做法其实跟“模板方法模式”有点点类似。在模板方法模式中,可以将可变的部分留给子类去重写,而将不变的部分由父类实现。那么在委托作为参数的情况下,Calculator可以自己处理不变的逻辑,而将“具体怎么做”的事情委托给他人去办理。

委托作为参数,在C#中非常常见。比如线程的创建,需要给一个ThreadStart或者ParameterizedThreadStart委托作为参数,而在线程执行的时候,将这个参数所指代的函数用作线程执行体。再比如:List<T>类型的Find方法的参数也是一个委托,它把“怎么去查找”或者说“怎么样才算找到”这个问题留给了开发人员。开发人员只需要定义一个参数为T,返回值为布尔型的函数,实现函数体,并将函数作为参数传给Find方法,就可以完成集合中元素的查找。

委托作为返回值一般会用在“根据不同情况决定使用不同的委托”这样的情形下。这有点像工厂模式,不过委托用作返回值还是用的没有用作参数这样频繁。

与委托相关的概念还有很多,比如异步调用、泛型委托、匿名方法、Lambda表达式、事件、协变与逆变等。我会在后续的文章中陆续介绍。

C#基础:委托 【转】的更多相关文章

  1. C#基础委托回顾

    C#基础委托回顾 前言 快忘记了. 委托的特点 委托类似于 C++ 函数指针,但它们是类型安全的. 委托允许将方法作为参数进行传递. 委托可用于定义回调方法. 委托可以链接在一起:例如,可以对一个事件 ...

  2. C#基础---委托的使用

    一:什么是委托     委托是一种定义方法签名的类型当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法.委托是一个引用类型,所以它具有引用类型所具有的通性.它保存 ...

  3. [C#基础] 委托

    什么是委托 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有 ...

  4. c#核心基础-委托

    委托是一个类型.C#中的委托是面向对象的,并且它是类型安全的 当创建委托实例的时候,创建的实例会包含一个调用列表,在调用列表中可以包含多个方法.每个方法称作一个调用实体.调用实体可以是静态方法,也可以 ...

  5. C#基础-委托与事件

    委托 delegate是申明委托的关键字 返回类型都是相同的,并且参数类型个数都相同 委托声明 delegate double DelOperater(double num1, double num2 ...

  6. SQL数据库基础————委托

    委托:也称为代理,事件也是一种委托:定义在类的最外面 1.定义委托关键字:delegate函数签名:签名和函数保持一致定义委托的时候要根据函数来定义public delegate int First( ...

  7. C# 基础 - 委托、事件

    1. 委托 sequenceDiagram 方法->>委托: 返回值和入参一样 委托->>方法: 调用委托就是调用绑定的方法 delegate int NumTest(int ...

  8. C#委托基础

    转载自 http://woshixy.blog.51cto.com/5637578/1070976     C#委托基础1——委托基础   委托和其委托的方法必须具有相同的签名.签名相同:1.参数类型 ...

  9. C#基础---事件的使用

    一:什么是事件     事件是可以被控件识别的操作,如按下确定按钮,选择某个单选按钮或者复选框.每一种控件有自己可以识别的事件,如窗体的加载.单击.双击等事件,编辑框(文本框)的文本改变事件,等等.事 ...

  10. .net基础系列

    这里汇总了.net基础的相关文章,方便查阅! .net基础 委托(1)认识委托 委托(2).net 1.x中的委托 委托(3).net 2.0中的委托 委托(4).net 3.5中的委托 委托(5)委 ...

随机推荐

  1. Cuckoo hash算法分析

    一 基本思想: cuckoo hash是一种解决hash冲突的方法,其目的是使用简单的hash 函数来提高hash table的利用率,同时保证O(1)的查询时间 基本思想是使用2个hash函数来处理 ...

  2. XMind快捷键可以自定义吗

    在使用快捷键的时候,不知你是否有过这样的疑问,为什么这个操作的快捷键一定要是这个呢,我为什么不能换成其他的按键呢.其实这些在XMind思维导图中都是可以更改的,用户可以根据自己的操作习惯来定义快捷键命 ...

  3. IOS Application生命周期

    第一阶段 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *) ...

  4. IOS 排序算法

    /** * @brief 冒泡排序法 * * @param arr 需要排序的数组 */ -(void)BubbleSort:(NSMutableArray *)arr { // 取第一个与其邻接的对 ...

  5. 数据库的优化tips

    数据库   TIPS:: 1.用于记录或者是数据分析的表创建时::使用Id作为主键,1,2,3...表示消息条数.用户账号id用于做外键.一个用户相应唯一个accountId             ...

  6. Longest Palindromic Substring-----最长回文子串

    首先讲讲什么是回文, 看看Wiki是怎么说的:回文,亦称回环,是正读反读都能读通的句子.亦有将文字排列成圆圈者,是一种修辞方式和文字游戏.回环运用得当.能够表现两种事物或现象相互依靠或排斥的关系, 比 ...

  7. HDU 4521 间隔》=1的LIS 线段树+dp

    九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11991119 题意: n个数 d个距离 下面n个数的序列,求序列中的最长单调递增 ...

  8. pt-table-checksum解读

    pt-table-checksum是目前可以说是最好的查看主从一致性的工具 先来个使用例子,有助快速上手使用 在主库执行: mysql>GRANT SELECT, PROCESS, SUPER, ...

  9. [Manacher][HDU3613][Best Reward]

    题意: 将一段字符串 分割成两个串 如果分割后的串为回文串,则该串的价值为所有字符的权值之和(字符的权值可能为负数),否则为0. 问如何分割,使得两个串权值之和最大 思路: 裸的: 枚举分割点,计算, ...

  10. VS2013报表设计常用表达式

    一.页眉 1."日期"表达式:="日期: "& Today.ToShortDateString() 效果: 2.格式化日期:="日期: &qu ...