一、浅谈委托

如果有个过winform 和webform 程序开发的小伙伴一定有个这样的感觉吧,点击Button直接就执行了那个方法,到此他是怎么实现了的呢,大家有考虑过没有?

回到正题,什么是委托呢?委托,我们可以把看着是一个作为方法参数的一个方法,为什么呢,因为委托可以作为作为方法的参数,而给委托赋的值都是方法。下面我举一个例 

  1.    /// <summary>
       /// 定义的一个打招呼的委托
  2. /// </summary>
  3. /// <param name="name"></param>
  4. public delegate void GreetingDelegate(string name);
  5.  
  6. /// <summary>
  7. /// 中国人打招呼的类
  8. /// </summary>
  9. public class Chinese
  10. {
  11. public void ChineseGreeting(string name)
  12. {
  13. Console.Write("早上好--" + name);
  14. }
  15. }
  16.  
  17. public class English
  18. {
  19. public void EnglishGreeting(string name)
  20. {
  21. Console.Write("Good Morning--" + name);
  22. }
  23. }
  24. class Program
  25. {
  26. static void Main(string[] args)
  27. {
  28. Chinese people1 = new Chinese();
  29. English people2 = new English();
  30. Greeting("欢大少", people1.ChineseGreeting);
  31. Console.Write("\n");
  32. Greeting("Master", people2.EnglishGreeting);
  33. Console.ReadKey();
  34.  
  35. }
  36. private static void Greeting(string name,GreetingDelegate MakingGreeting )
  37. {
  38. MakingGreeting(name);
  39. }
  40. }

运行结果

当然,实质上委托是一个特殊的类,知识有限,只能讲到这儿了,

事件是什么呢,其实事件就是用event修饰后的委托,

  1.    class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Publishser pb = new Publishser();
  6. Subscriber sb = new Subscriber();
  7. //pb.NumberChange += sb.OnNumberChange;
  8. pb.NumberChange = sb.OnNumberChange;
  9. pb.DoSomething();
  10. pb.NumberChange(100);
  11. Console.ReadLine();
  12. }
  13. }
  14.  
  15. /// <summary>
  16. /// 定义委托
  17. /// </summary>
  18. public delegate void NumberChangeEventHandler(int count);
  19.  
  20. public class Publishser
  21. {
  22. private int count;
  23. public NumberChangeEventHandler NumberChange;
  24. //public event NumberChangeEventHandler NumberChange;
  25. public void DoSomething()
  26. {
  27. if(NumberChange!=null)
  28. {
  29. count++;
  30. NumberChange(count);
  31. }
  32. }
  33. }
  34.  
  35. public class Subscriber
  36. {
  37. public void OnNumberChange(int count)
  38. {
  39. Console.WriteLine("Subscriber notified count ={0}", count);
  40. }
  41. }

上面的代码如果是定义普通的委托能够正常运行,但如果换成事件来的话变异不能通过,为什么呢?因为为了更好的封装性,实际是事件是一个私有变量,外部不是访问,如果用委托变量,外部能够调用委托,影响封装性,就像上面代码

  1. pb.NumberChange(100);,如果定义为事件,那么NumberChange只能通过内部方法DoSomething来调用。

事件只能通过+=来进行赋值,如果你反编译你可以看到事件里有两个方法 Add() 和Remove(),分别对应的是+=和-=。

二、winform程序click事件的原理

在form的构造函数中,我们能看到下面的代码

  1.      /// <summary>
  2. /// 设计器支持所需的方法 - 不要
  3. /// 使用代码编辑器修改此方法的内容。
  4. /// </summary>
  5. private void InitializeComponent()
  6. {
  7. this.button1 = new System.Windows.Forms.Button();
  8. this.SuspendLayout();
  9. //
  10. // button1
  11. //
  12. this.button1.Location = new System.Drawing.Point(, );
  13. this.button1.Name = "button1";
  14. this.button1.Size = new System.Drawing.Size(, );
  15. this.button1.TabIndex = ;
  16. this.button1.Text = "button1";
  17. this.button1.UseVisualStyleBackColor = true;
  18. this.button1.Click += new System.EventHandler(this.button1_Click);
  19. //
  20. // Form1
  21. //
  22. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
  23. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  24. this.ClientSize = new System.Drawing.Size(, );
  25. this.Controls.Add(this.button1);
  26. this.Name = "Form1";
  27. this.Text = "F1";
  28. this.ResumeLayout(false);
  29.  
  30. }

我们发现对事件的添加 this.button1.Click += new System.EventHandler(this.button1_Click);

这个地方我们只是添加了事件,但这个事件是怎么触发的呢?我们进行调试

button的click的触发经过如下过程

三、模拟winform事件

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8.  
  9. namespace MonitorEvent
  10. {
  11. /// <summary>
  12. /// 定义委托
  13. /// </summary>
  14. /// <param name="sender"></param>
  15. /// <param name="e"></param>
  16. public delegate void MonitorEventHandler(object sender, EventArgs e);
  17.  
  18. /// <summary>
  19. /// 时间数据类
  20. /// </summary>
  21. public class MsgEventArgs : EventArgs
  22. {
  23. /// <summary>
  24. /// 修改时间
  25. /// </summary>
  26. public DateTime ChanggeTime { get; set; }
  27.  
  28. /// <summary>
  29. /// 提示信息
  30. /// </summary>
  31. public string ToSend { get; set; }
  32. public MsgEventArgs(DateTime changgeTime, string toSend)
  33. {
  34. this.ChanggeTime = changgeTime;
  35. this.ToSend = toSend;
  36. }
  37. }
  38. /// <summary>
  39. /// 事件订阅者
  40. /// </summary>
  41. public class MonitorText
  42. {
  43. public string name = "文本文档";
  44. //定义监控文本事件
  45. public event MonitorEventHandler MonitorEvent;
  46. //上次文件更新时间用于判断文件是否修改过
  47. private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
  48. public MonitorText()
  49. {
  50.  
  51. }
  52. // 文件更新调用
  53. protected virtual void OnTextChange(MsgEventArgs e)
  54. {
  55. if (MonitorEvent != null)
  56. {
  57. //不为空,处理事件
  58. MonitorEvent(this, e);
  59. }
  60. }
  61.  
  62. //事件监听的方法
  63. public void BeginMonitor()
  64. {
  65. DateTime bCurrentTime;
  66.  
  67. while (true)
  68. {
  69. bCurrentTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
  70. if (bCurrentTime != _lastWriteTime)
  71. {
  72. _lastWriteTime = bCurrentTime;
  73. MsgEventArgs msg = new MsgEventArgs(bCurrentTime, "文本改变了");
  74. OnTextChange(msg);
  75. }
  76. //0.1秒监控一次
  77. Thread.Sleep();
  78. }
  79. }
  80.  
  81. }
  82.  
  83. /// <summary>
  84. /// 事件监听者
  85. /// </summary>
  86. public class Administrator
  87. {
  88. //管理员事件处理方法
  89. public void OnTextChange(object Sender, EventArgs e)
  90. {
  91. MonitorText monitorText = (MonitorText)Sender;
  92. Console.WriteLine("尊敬的管理员:" + DateTime.Now.ToString() + ": " + monitorText.name + "发生改变.");
  93. }
  94. }
  95.  
  96. class Program
  97. {
  98. static MonitorText MonitorTextEventSource;
  99. static void Main(string[] args)
  100. {
  101. MonitorTextEventSource = new MonitorText();
  102. //1. 启动后台线程添加监视事件
  103. var thrd = new Thread(MonitorTextEventSource.BeginMonitor);
  104. thrd.IsBackground = true;
  105. thrd.Start();
  106. //2实例化管理员类
  107. Administrator ad = new Administrator();
  108. //4订阅事件
  109. MonitorTextEventSource.MonitorEvent += ad.OnTextChange;
  110. Console.ReadLine();
  111. }
  112. }
  113. }

四、申明

文中的观点多来源与张子阳的.net之美和ATtuing的博客,希望大家共同学习

用winform程序来了解委托和事件的更多相关文章

  1. (.NET高级课程笔记)委托、事件总结

      1.委托的声明.实例化和调用 同样的,也可以把事务写成上面的形式 2.泛型委托---Func.Action 3.委托的意义:解耦 4.委托的意义:异步多线程 5.委托的意义:多播委托 6.观察者模 ...

  2. C#委托和事件的使用的意义

    转载自:https://www.cnblogs.com/yinqixin/p/5056307.html 每一个初学C#的程序猿,在刚刚碰到委托和事件的概念时,估计都是望而却步,茫然摸不到头脑的.百度一 ...

  3. 编写高质量代码改善C#程序的157个建议——建议137:委托和事件类型应添加上级后缀

    建议137:委托和事件类型应添加上级后缀 委托类型本身是一个类,考虑让派生类的名字以基类名字作为后缀.事件类型是一类特殊的委托,所以事件类型也遵循本建议. 委托和事件的正确的命名方式有: public ...

  4. CS中委托与事件的使用-以Winform中跨窗体传值为例

    场景 委托(Delegate) 委托是对存有某个方法的引用的一种引用类型变量. 委托特别用于实现事件和回调方法. 声明委托 public delegate int MyDelegate (string ...

  5. winform子窗口与父窗口的交互-使用委托与事件

    实现子窗口与父窗口的交互,通过父窗口调用并控制子窗口,子窗口也能控制父窗口,使用委托和事件的方法,可以实现. 1.父窗口调用子窗口,并通过子窗口控制父窗口 新建工程,创建两个窗体    显示子窗体的代 ...

  6. winform使用委托和事件在窗体之间传值

    定义委托和事件,并且触发这个事件 //定义委托 public delegate void ShowOutStockDelegate(List<OutStockResultDto> outS ...

  7. .NET面试题系列[7] - 委托与事件

    委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...

  8. C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

    使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...

  9. 从web页面启动winform程序的实现方法

    本文实现的需求是: A.通过web页面启动winform程序: B.将页面的参数传递给winform程序: C.winform程序已经启动并正在运行时,从web页面不能重新启动winform程序,只是 ...

随机推荐

  1. 12月15日smarty模板基本语法

    smarty基本语法: 1.注释:<{* this is a comment *}>,注意左右分隔符的写法,要和自己定义的一致. <{* I am a Smarty comment, ...

  2. [git] warning: LF will be replaced by CRLF | fatal: CRLF would be replaced by LF

    遇到这两个错误,是因为Git的换行符检查功能. core.safecrlf Git提供了一个换行符检查功能(core.safecrlf),可以在提交时检查文件是否混用了不同风格的换行符.这个功能的选项 ...

  3. Java国际化(i18n)

    Java国际化(i18n) 最近在做一个网站国际化的功能.用Java做开发,使用spring+velocity. Java提供了对i18n的支持,spring对其做了集成,可以很方便的配置.主要思想就 ...

  4. Python 简易聊天机器人

    聊天机器人 | |-----MySql | |---module--"逻辑运算层" | | | |---ciku--"与词库交互" | | | |---dict ...

  5. android 弹出AlertDialog的学习案例

    我在编写的时候,测试的关键代码: AlertDialog.Builder builder=new AlertDialog.Builder(MainPointListActivity.this); bu ...

  6. php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密

    PHP使用openssl进行Rsa加密,如果要加密的明文太长则会出错,解决方法:加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文:解密的时候需要128个字符解密一下,然后拼接成数据. 加 ...

  7. 深入理解 JavaScript 变量的作用域和作用域链

    一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...

  8. ORA-01033 ORACLE 正在初始化或关闭

    (借鉴:该方法本人亲自操作过,解决了问题!) 解决连接ORACLE错误一例:ORA-01033: ORACLE 正在初始化或关闭 客户发现连接数据库有问题,错误有: ORA-01033: ORACLE ...

  9. hdu 4329

    problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟  a.     p(r)=   R'/i   rel(r)=(1||0)  R ...

  10. php mysqli mysqli_query() mysqli_real_query()

    2016年11月26日 15:22:27 星期六 场景: PHP从mysql中读取数据 1. 一次性读取所有数据返给PHP 2. 每次循环只读取一掉记录 数据量小的时候可以使用第一种方法, 数据量很大 ...