一、浅谈委托

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

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

   /// <summary>
   /// 定义的一个打招呼的委托
/// </summary>
/// <param name="name"></param>
public delegate void GreetingDelegate(string name); /// <summary>
/// 中国人打招呼的类
/// </summary>
public class Chinese
{
public void ChineseGreeting(string name)
{
Console.Write("早上好--" + name);
}
} public class English
{
public void EnglishGreeting(string name)
{
Console.Write("Good Morning--" + name);
}
}
class Program
{
static void Main(string[] args)
{
Chinese people1 = new Chinese();
English people2 = new English();
Greeting("欢大少", people1.ChineseGreeting);
Console.Write("\n");
Greeting("Master", people2.EnglishGreeting);
Console.ReadKey(); }
private static void Greeting(string name,GreetingDelegate MakingGreeting )
{
MakingGreeting(name);
}
}

运行结果

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

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

   class Program
{
static void Main(string[] args)
{
Publishser pb = new Publishser();
Subscriber sb = new Subscriber();
//pb.NumberChange += sb.OnNumberChange;
pb.NumberChange = sb.OnNumberChange;
pb.DoSomething();
pb.NumberChange(100);
Console.ReadLine();
}
} /// <summary>
/// 定义委托
/// </summary>
public delegate void NumberChangeEventHandler(int count); public class Publishser
{
private int count;
public NumberChangeEventHandler NumberChange;
//public event NumberChangeEventHandler NumberChange;
public void DoSomething()
{
if(NumberChange!=null)
{
count++;
NumberChange(count);
}
}
} public class Subscriber
{
public void OnNumberChange(int count)
{
Console.WriteLine("Subscriber notified count ={0}", count);
}
}

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

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

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

二、winform程序click事件的原理

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

     /// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(, );
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(, );
this.button1.TabIndex = ;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(, );
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "F1";
this.ResumeLayout(false); }

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

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

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

三、模拟winform事件

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace MonitorEvent
{
/// <summary>
/// 定义委托
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void MonitorEventHandler(object sender, EventArgs e); /// <summary>
/// 时间数据类
/// </summary>
public class MsgEventArgs : EventArgs
{
/// <summary>
/// 修改时间
/// </summary>
public DateTime ChanggeTime { get; set; } /// <summary>
/// 提示信息
/// </summary>
public string ToSend { get; set; }
public MsgEventArgs(DateTime changgeTime, string toSend)
{
this.ChanggeTime = changgeTime;
this.ToSend = toSend;
}
}
/// <summary>
/// 事件订阅者
/// </summary>
public class MonitorText
{
public string name = "文本文档";
//定义监控文本事件
public event MonitorEventHandler MonitorEvent;
//上次文件更新时间用于判断文件是否修改过
private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
public MonitorText()
{ }
// 文件更新调用
protected virtual void OnTextChange(MsgEventArgs e)
{
if (MonitorEvent != null)
{
//不为空,处理事件
MonitorEvent(this, e);
}
} //事件监听的方法
public void BeginMonitor()
{
DateTime bCurrentTime; while (true)
{
bCurrentTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
if (bCurrentTime != _lastWriteTime)
{
_lastWriteTime = bCurrentTime;
MsgEventArgs msg = new MsgEventArgs(bCurrentTime, "文本改变了");
OnTextChange(msg);
}
//0.1秒监控一次
Thread.Sleep();
}
} } /// <summary>
/// 事件监听者
/// </summary>
public class Administrator
{
//管理员事件处理方法
public void OnTextChange(object Sender, EventArgs e)
{
MonitorText monitorText = (MonitorText)Sender;
Console.WriteLine("尊敬的管理员:" + DateTime.Now.ToString() + ": " + monitorText.name + "发生改变.");
}
} class Program
{
static MonitorText MonitorTextEventSource;
static void Main(string[] args)
{
MonitorTextEventSource = new MonitorText();
//1. 启动后台线程添加监视事件
var thrd = new Thread(MonitorTextEventSource.BeginMonitor);
thrd.IsBackground = true;
thrd.Start();
//2实例化管理员类
Administrator ad = new Administrator();
//4订阅事件
MonitorTextEventSource.MonitorEvent += ad.OnTextChange;
Console.ReadLine();
}
}
}

四、申明

文中的观点多来源与张子阳的.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. ThinkPhp 3.2 自动验证

    自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 数据验证有两种方式: 静态方式:在模型类里面通过$_validate属性定义验证规则 ...

  2. 图解JVM执行引擎之方法调用

    一.方法调用 方法调用不同于方法执行,方法调用阶段的唯一任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程.Class文件的编译过程中不包括传统编译器中的连接步骤,一 ...

  3. vim删除以#,空格开头的行

    1,删除以#号开头的行: :g/^#/d :%s/^#.*\n 2,删除以空格开头的行: :g/^\s/d                “\s代表空格” :%s/^\s.*\n 3,删除以空格#开头 ...

  4. maven热部署到tomcat

    1添加tomcat用户,在conf/tomcat-user.xml文件下添加一个tomcat用户 <role rolename="manager-gui"/> < ...

  5. 前端React开发入门笔记

    什么是React React是一个JavaScript库,是由FaceBook和Instagram开发的,主要用于用户创建图形化界面. Hello world <!DOCTYPE html> ...

  6. STM32 复合设备编写

    目的 完成一个CDC + MSC的复合USB设备 可以方便在CDC,MSC,复合设备三者间切换 可移植性强 预备知识 cube中USB只有两个入口. main函数中的MX_USB_DEVICE_Ini ...

  7. 强有力的Linux历史命令 你还记得几个

    列出所有出现到的命令:(所有一下信息都可以通过man history得到,而且还更多) history:列出历史中执行过的命令(-c清除所有的命令历史) !N:执行编号为N的历史命令 !-N:执行倒数 ...

  8. knn-伪代码与实现过程

    knn特点 优点:精度高,对异常值不明感,无数据输入嘉定 缺点:计算复杂度高,空间复杂度高 适用范围:数值型和标称型 knn算法的伪代码 1.计算已知类别数据集中的点与当前之间的距离 2.按照距离递增 ...

  9. jemter的安装和使用

    1.下载地址:http://jmeter.apache.org/download_jmeter.cgi 2.安装 (1)解压,解压之后如图 (2)配置环境变量 我解压之后的目录是:D:\softwar ...

  10. doT.js

    最近用到的数据模板引擎有很多,今天讲的doT.js也是其中一种. doT.js的特点是体积小,速度快,并且不依赖其他插件. 官网下载:http://olado.github.io 下面是用法: 模板引 ...