第一部分:C#语言基础----委托和事件

淡淡的烟草味﹌ 2021-06-24 16:10 520阅读 0赞

第3章 C#中的委托和事件

3.1 理解委托

3.1.1 将方法作为方法的参数

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

  1. public void EnglishGreeting(string name)
  2. {
  3. Console.WriteLine("Morning, " + name);
  4. }
  5. public void ChineseGreeting(string name)
  6. {
  7. Console.WriteLine("早上好, " + name);
  8. }

2.定义一个委托

  1. public delegate void GreetDelegate(string name);

3.定义一个使用委托的方法

  1. //注意此方法,它接受一个GreetingDelegate类型的方法作为参数
  2. public static void GreetPeople(string name, GreetDelegate MakeGreeting)
  3. {
  4. MakeGreeting(name);
  5. }

4.使用委托方法

  1. static void Main(string[] args)
  2. {
  3. GreetPeople("zzh",EnglishGreeting);
  4. GreetPeople("中华",ChineseGreeting);
  5. Console.ReadLine();
  6. }

2789632-d4bc29ae29776f86.png

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

2789632-0f6499ebf849614a.png

第三种方式,绕过GreetPeople方法(比较喜欢这种方法)

2789632-e94d7ec0ad4031fc.png

既然委托可以绑定一个方法,那么也应该有办法取消对方法的绑定,很容易想到,这个语法是“-=”。

3.2 事件的由来

使用事件不仅能获得比委托更好的封装性,还能限制含有事件的类型的能力。
1.首先,准备两个方法:

  1. public static void EnglishGreeting(string name)
  2. {
  3. Console.WriteLine("Morning, " + name);
  4. }
  5. public static void ChineseGreeting(string name)
  6. {
  7. Console.WriteLine("早上好, " + name);
  8. }

2.然后呢,准备一个一个委托类型

  1. //定义委托,它定义了可以代表的方法的类型
  2. public delegate void GreetingDelegate(string name);

3.接着准备一个事件,来使用这个委托类型(此处放在一个GreepManager类中)

  1. public class GreetingManager
  2. {
  3. //声明事件
  4. public event GreetingDelegate MakeGreet;
  5. public void GreetPeople(string name)
  6. {
  7. MakeGreet(name);
  8. }
  9. }

4.最后使用这个事件方法

  1. static void Main(string[] args)
  2. {
  3. GreetingManager gm = new GreetingManager();
  4. gm.MakeGreet += EnglishGreeting;//注意此处,并没用使用先赋值的方式
  5. gm.MakeGreet += ChineseGreeting;
  6. gm.GreetPeople("zzh");
  7. }

2789632-9a3ccac4a1f585ee.png

3.2.2 限制类型能力

使用事件不仅能获得比委托更好的封装性,还能限制含有事件的类型的能力。这是什么意思呢?它的意思是说:事件应该由事件的发布者触发,而不应该由事件的客户端(客户程序)来触发。
1.首先定义一个委托

  1. // 定义委托
  2. public delegate void NumberChangedEventHandler(int count);

2.然后呢,定义一个事件发布者

  1. // 定义事件发布者
  2. public class Publishser
  3. {
  4. private int count;
  5. public NumberChangedEventHandler NumberChanged; // 声明委托变量
  6. public void DoSomething()
  7. {
  8. // 在这里完成一些工作 ...
  9. if (NumberChanged != null)
  10. { // 触发事件
  11. count++;
  12. NumberChanged(count);
  13. }
  14. }
  15. }

3.接着定义一个事件接收者

  1. // 定义事件订阅者
  2. public class Subscriber
  3. {
  4. public void OnNumberChanged(int count)
  5. {
  6. Console.WriteLine("Subscriber notified: count = {0}", count);
  7. }
  8. }

4.最后就是使用事件了

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Publishser pub = new Publishser();
  6. Subscriber sub = new Subscriber();
  7. pub.NumberChanged += new NumberChangedEventHandler(sub.OnNumberChanged);
  8. pub.DoSomething(); // 应该通过DoSomething()来触发事件
  9. pub.NumberChanged(100); // 也可以被这样直接调用,对委托变量的不恰当使用
  10. Console.ReadLine();
  11. }
  12. }

理解:首先声明发布者和接收者,然后为发布者里的委托变量赋值,调用订阅者的方法,使用发布者里面的方法,启动事件的发生,然后……有点绕,再看看吧……
这里还有一个约定俗称的规定,就是订阅事件的方法的命名,通常为“On事件名”,比如这里的OnNumberChanged。

3.4 .NET框架中的委托和事件

假设有个高档的热水器,当水温超过95度的时候:一、扬声器会开始发出语音,告诉你水的温度;二、液晶屏也会改变水温的显示,以提示水已经快烧开了。现在需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,将它取名为Heater,它有代表水温的字段temperature,当然,还有必不可少的水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace TestEventAndDelegate
  7. {
  8. public class Heater
  9. {
  10. private int temperature; // 水温
  11. // 烧水
  12. public void BoilWater()
  13. {
  14. for (int i = 0; i <= 100; i++)
  15. {
  16. temperature = i;
  17. if (temperature > 95)
  18. {
  19. MakeAlert(temperature);
  20. ShowMsg(temperature);
  21. }
  22. }
  23. }
  24. // 发出语音警报
  25. private void MakeAlert(int param)
  26. {
  27. Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
  28. }
  29. // 显示水温
  30. private void ShowMsg(int param)
  31. {
  32. Console.WriteLine("Display:水快开了,当前温度:{0}度。", param);
  33. }
  34. }
  35. class Program
  36. {
  37. static void Main()
  38. {
  39. Heater ht = new Heater();
  40. ht.BoilWater();
  41. Console.ReadLine();
  42. }
  43. }
  44. }
3.4.3 实现示例的Observer设计模式
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace TestEventAndDelegate
  7. {
  8. // 热水器
  9. public class Heater
  10. {
  11. private int temperature;
  12. public delegate void BoilHandler(int param); //声明委托
  13. public event BoilHandler BoilEvent; //声明事件
  14. // 烧水
  15. public void BoilWater()
  16. {
  17. for (int i = 0; i <= 100; i++)
  18. {
  19. temperature = i;
  20. if (temperature > 95)
  21. {
  22. if (BoilEvent != null)
  23. { //如果有对象注册
  24. BoilEvent(temperature); //调用所有注册对象的方法
  25. }
  26. }
  27. }
  28. }
  29. }
  30. // 警报器
  31. public class Alarm
  32. {
  33. public void MakeAlert(int param)
  34. {
  35. Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
  36. }
  37. }
  38. // 显示器
  39. public class Display
  40. {
  41. public static void ShowMsg(int param)
  42. { //静态方法
  43. Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
  44. }
  45. }
  46. class Program
  47. {
  48. static void Main()
  49. {
  50. Heater heater = new Heater();
  51. Alarm alarm = new Alarm();
  52. heater.BoilEvent += alarm.MakeAlert; //注册方法
  53. heater.BoilEvent += (new Alarm()).MakeAlert; //为匿名对象注册方法
  54. heater.BoilEvent += Display.ShowMsg; //注册静态方法
  55. heater.BoilWater();//烧水,会自动调用注册过对象的方法
  56. Console.ReadLine();
  57. }
  58. }
  59. }

3.5 委托进阶

发表评论

表情:
评论列表 (有 0 条评论,520人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C# 基础知识系列- 11 委托事件

    0. 前言 事件和委托是C\中的高级特性,也是C\中很有意思的一部分。出现事件的地方,必然有委托出现;而委托则不一定会有事件出现。那为什么会出现这样的关系呢?这就需要从事

    相关 C# 中的委托事件

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C\时间不长的人来说并不容易。它们就像是一道槛儿,过了这个槛的人

    相关 委托事件

    委托 委托就是将方法当作变量来使用。把委托作为方法的一个载体,方法好像参数一样可以被传递,并进行运算。委托相当于函数的工厂。委托是类型,就好像类是类型一样。(类封装了方法

    相关 第一部分C#语言基础

    第1章 C\类型基础 C\中的两种类型:值类型和引用类型 1.1 值类型和引用类型 值类型包括了结构和枚举,引用类型则包括了类、接口、委托等。还有一种特殊的值类型

    相关 C#——委托事件

    一、委托         说道委托,很多的教材上都说是类似于C语言上的指针,但是以我理解的程度来看,更像是复制这个方法或函数的使用,因为委托可以看成是一个数据类型一样的东