C#学习笔记(七)

第七讲 委托1

委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,

委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。

下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。

public delegate void Del(string message);

委托具有以下特点:

  • 委托类似于 C++ 函数指针,但它是类型安全的。

  • 委托允许将方法作为参数进行传递。

  • 委托可用于定义回调方法。

  • 委托可以链接在一起;例如,可以对一个事件调用多个方法。

  • 方法不需要与委托签名精确匹配。有关更多信息,请参见协变和逆变

  • C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替

  • 单独定义的方法。

  1. using System;
  2. //创建一个类
  3. class MyDelegate
  4.     //创建一个静态函数:张三吃东西。
  5.     //字符串的参数food
  6.     static void zsEat(string food)
  7.     {
  8.         //在屏幕上打印
  9.         Console.WriteLine("张三吃" + food);
  10.     }
  11.     static void Main()
  12.     {
  13.         //调用
  14.         zsEat("西瓜");
  15.     }
  16. }

这个程序很简单,就是为了打印张三吃食物。大家自己编译执行下,不是很难理解。

结果是张三吃西瓜。下面我们来改下这段程序,通过委托的方法来调用张三吃东西

这个函数。

  1. using System;
  2. /// <summary>
  3. /// 声明一个EatDelegate这样的委托
  4. /// 委托的声明首先使用了delegate关键字,然后是委托的返回值void,括号里是委托的参数
  5. /// 委托原型必须跟域委托的方法具有相同的返回值和参数(个数也必须一致)
  6. /// 域委托的方法就是MeDelegate类下的void zsEat(string food)方法
  7. /// 委托的本质就是一个类,任何可以声明的地方都可以声明委托
  8. /// </summary>
  9. /// <param name="food"></param>
  10. delegate void EatDelegate(string food);

  11. class MyDelegate
  12.     static void zsEat(string food)
  13.     {
  14.         Console.WriteLine("张三吃" + food);
  15.     }
  16.     static void Main()
  17.     {
  18.         //下面我们就可以通过调用委托来调用张三吃西瓜这个函数了
  19.         //这里声明了一个委托的实例zs并给它初始化
  20.         //EatDelegate里面带的参数是我们域代理的函数的名称
  21.         //这就意味着zs这个委托实例它所代理的函数的名字叫zsEat,两者之间能联系
  22.         EatDelegate zs = new EatDelegate(zsEat);
  23.         //进行调用使用函数
  24.         zs("西瓜");
  25.     }
  26. }

我们进行执行编译代码,结果和上面是一样的。而这一次我们并没有直接

使用zsEat这个函数,而是通过代理zs来调用它,它们的执行效果都是一样

的。好,接下来张三一个人吃西瓜觉得不过瘾,我们添加李四等人,

代码如下:

  1. using System;
  2. delegate void EatDelegate(string food);
  3. class MyDelegate
  4.     static void zsEat(string food)
  5.     {
  6.         Console.WriteLine("张三吃" + food);
  7.     }
  8.     //添加一个李四吃东西函数
  9.     static void lsEat(string food)
  10.     {
  11.         Console.WriteLine("李四吃" + food);
  12.     }
  13.     //添加一个王五吃东西函数
  14.     static void wwEat(string food)
  15.     {
  16.         Console.WriteLine("王五吃" + food);
  17.     }
  18.     static void Main()
  19.     {
  20.         EatDelegate zs = new EatDelegate(zsEat);
  21.         EatDelegate ls = new EatDelegate(lsEat);
  22.         EatDelegate ww = new EatDelegate(wwEat);
  23.         //进行调用使用函数
  24.         zs("西瓜");
  25.         ls("西瓜");
  26.         ww("西瓜");
  27.     }
  28. }

屏幕上也打印出来了张三,王五,李四都在吃西瓜,没有什么问题。

但是他们都在吃同一样东西西瓜,为什么我们要输入三次呢?这样

不是很麻烦嘛,有没有什么办法可以只输入一次西瓜,而同时都调用

了这3个函数了呢?有的,委托链可以实现这样的功能。这也是委托一

个十分强大的地方,我们修改下代码,声明委托链:

  1. using System;
  2. delegate void EatDelegate(string food);
  3. class MyDelegate
  4.     static void zsEat(string food)
  5.     {
  6.         Console.WriteLine("张三吃" + food);
  7.     }
  8.     static void lsEat(string food)
  9.     {
  10.         Console.WriteLine("李四吃" + food);
  11.     }
  12.     static void wwEat(string food)
  13.     {
  14.         Console.WriteLine("王五吃" + food);
  15.     }
  16.     static void Main()
  17.     {
  18.         EatDelegate zs = new EatDelegate(zsEat);
  19.         EatDelegate ls = new EatDelegate(lsEat);
  20.         EatDelegate ww = new EatDelegate(wwEat);
  21.         //声明一个委托链,不需要实例化
  22.         EatDelegate eatChain;
  23.         //接下来把张三李四王五都加进这个委托链
  24.         eatChain = zs + ls + ww;
  25.         //现在让他们一起吃西瓜
  26.         eatChain("西瓜");
  27.     }
  28. }

我们保存代码执行,效果如下:

我们看,我们只使用了一次西瓜的参数,就让张三李四王五同

时吃西瓜了。我们回过头来再来看下代码,(eatChain = zs + ls + ww)

在委托链eatChain中,只要把张三李四王五这几个委托的实例加到

这个委托链里面,之后向调用方法一样调用这个委托链eatChain("西瓜"),它就会依次

按照上面加入的顺序去执行这几个委托所对应的函数了。

  好,接下来我们把程序变得更具有逻辑性些:

  1. using System;
  2. delegate void EatDelegate(string food);
  3. class MyDelegate
  4.     static void zsEat(string food)
  5.     {
  6.         Console.WriteLine("张三吃" + food);
  7.     }
  8.     static void lsEat(string food)
  9.     {
  10.         Console.WriteLine("李四吃" + food);
  11.     }
  12.     static void wwEat(string food)
  13.     {
  14.         Console.WriteLine("王五吃" + food);
  15.     }
  16.     static void Main()
  17.     {
  18.         EatDelegate zs = new EatDelegate(zsEat);
  19.         EatDelegate ls = new EatDelegate(lsEat);
  20.         EatDelegate ww = new EatDelegate(wwEat);
  21.         //声明一个委托链,不需要实例化
  22.         EatDelegate eatChain;
  23.         //张三李四王五刚刚放假,非常高兴决定搞一个party
  24.         Console.WriteLine("张三,李四,王五开座谈会");
  25.         //他们三个人都在吃西瓜呀
  26.         eatChain = zs + ls + ww;
  27.         eatChain("西瓜");
  28.         //这个时候,李四的电话响了
  29.         Console.WriteLine("李四出去接电话");
  30.         //李四就吃不了西瓜了
  31.         eatChain -= ls;
  32.         //张三和王五继续吃香蕉
  33.         eatChain("香蕉");
  34.         //过了一会李四回来了
  35.         Console.WriteLine("李四回来了");
  36.         eatChain += ls;
  37.         //他们接着吃桔子
  38.         eatChain("桔子");
  39.     }
  40. }

我们来看下效果:

我们来看一下,前面他们3个人吃西瓜我们都理解了,这个时候李四

出去接电话了.我们用一个"-="将ls这个实例开除出eatChain这个

委托链,接着执行吃香蕉.我们可以在屏幕上看出只有张三和王五在

吃香蕉。这时李四又回来了,李四也要继续吃东西eatChain += ls

把李四又加了进去,接着他们一起吃桔子eatChain("桔子"),我们看

结果他们3个人又都在一起吃桔子了。

  C#其实重载了-=和+=这2个操作符来对委托链里的元素进行加减操作,

从而使得我们可以随意控制委托链里的元素个数。

  1.     static void zsEat(string food)
  2.     {
  3.         Console.WriteLine("张三吃" + food);
  4.     }
  5.     static void lsEat(string food)
  6.     {
  7.         Console.WriteLine("李四吃" + food);
  8.     }
  9.     static void wwEat(string food)
  10.     {
  11.         Console.WriteLine("王五吃" + food);
  12.     }

向这样只有几句话的委托方法微软提供了一种非常简单的书

写方式给我们,使得我们可以更方便的写出委托,

下面我们来修改下代码:

  1. using System;
  2. delegate void EatDelegate(string food);
  3. class MyDelegate
  4.     static void Main()
  5.     {
  6.         //声明一个委托链,给他赋一个空值
  7.         EatDelegate eatChain = null;
  8.         //三个人都在吃西瓜
  9.         eatChain += delegate(string food) { Console.WriteLine("张三吃" + food); };
  10.         eatChain += delegate(string food) { Console.WriteLine("李四吃" + food); };
  11.         eatChain += delegate(string food) { Console.WriteLine("王五吃" + food); };
  12.         eatChain("西瓜");
  13.     }
  14. }

 我们编译执行可以得到张三李四王五都在吃西瓜。虽然我们没有书写

zsEat(string food),lsEat(string food),wwEat(string food)

这些方法,但是呢我们把这些方法直接加到了委托链里面。当委托链执行

的时候,得出了刚才一样的效果(屏幕上3个人吃西瓜)。这个就是C#2.0新

增的匿名方法,它使的我们更加容易的去创建委托,有关匿名方法的讲解

可以去MSDN上的webcast网络讲座上,李建忠老师的《C#2.0锐利体验系

列课程》中的《匿名方法,迭代器》有深入详细的讲解,

若果感兴趣可以去下载学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值