1. 委托概述

“委托”相当于C++中的“函数指针”,委托必须与所要“指向”的函数在“参数”和“返回类型”上保持一致;

// 定义Person类
public class Person {public string Name = "Rain Man";public string Speak(string words) {Console.WriteLine(this.Name + " said: " + words);return words;}
}// 定义委托
public delegate string Dele_Speak(string str);class Program {static void Main(string[] args) {Person p = new Person();                    // 实例化Person类Dele_Speak dp = new Dele_Speak(p.Speak);    // 实例化委托:变量dp实际上就是指向p.Speak函数的指针dp("Welcome to my blog!");                  // 输出:Rain Man said: Welcome to my blog!Console.ReadLine();}
}
  • 代理“Dele_Speak”与“Speak”方法在参数和返回类型保持一致;
  • “Dele_Speak dp = new Dele_Speak(p.Speak)”,实际上就是创建了一个“dp”指针,指向“p.Speak”方法
  • “dp("Welcome to my blog!")”,实际上就是“p.Speak("Welcome to my blog!")”

2. 多路广播

// 定义Person类
public class Person {public string Speak(string words) {Console.WriteLine("Speak: " + words);return "111";}public string Say(string words) {Console.WriteLine("Say: " + words);return "222";}public string Translate(string words) {Console.WriteLine("Translate: " + words);return "333";}
}
// 声明代理
public delegate string Dele_Str(string str);class Program {static void Main(string[] args) {Person p = new Person();                            // 实例化Person类Dele_Str dp_Speak = new Dele_Str(p.Speak);          // 实例化委托指向 p.SpeakDele_Str dp_Say = new Dele_Str(p.Say);              // 实例化委托指向 p.SayDele_Str dp_Translate = new Dele_Str(p.Translate);  // 实例化委托指向 p.Transpate// 多路广播dp_Speak = dp_Speak + dp_Say;dp_Speak = dp_Speak + dp_Translate;string str = dp_Speak("Rain Man");Console.WriteLine(str); // 输出:333Console.ReadLine();}
}

在Person类中创建了三个函数:Speak、Say、Translate,这三个函数在参数和返回类型上相同,因此可是使用同一个委托(Dele_Str)。

多路委托:使用同一个委托“指向”不同的函数,使这几个函数可以“计算”,其执行逻辑如下:

执行:string str = dp_Speak("Rain Man");
输出:Speak: Rain ManSay: Rain ManTranslate: Rain Man实际上就是执行下述代码:p.Speak("Rain Man");p.Say("Rain Man");p.Translate("Rain Man");返回值:即最后一个函数的返回值

3. 事件代理

有两个窗体:

  • FrmMain:该窗体中有一个按钮“btnAdd”,当点击此按钮时通过ShowDialog()方法打开“FrmUserAdd”窗体
  • FrmUserAdd: 该窗体中有一个按钮“btnOK”,当点击此按钮时“对外”(对FrmMain窗体)发送一个“UserAddEvent”事件,通过该事件将“FrmUserAdd”中填写的“用户信息”传至“FrmMain”窗体中。

3.1 FrmUserAdd窗体:

public partial class FrmUserAdd : Form {// 1. 定义事件参数类public class UserAddEventArgs : EventArgs {public User AddedUser;public UserAddEventArgs(User user) {this.AddedUser = user;}}// 2. 定义委托,并指定参数类型public delegate void UserAddEventHandler(object sender, UserAddEventArgs e);// 3. 定义事件,并指定该事件的委托类型public event UserAddEventHandler UserAddEvent;private void btnOK_Click(object sender, EventArgs e) {User user = new User(1, "Rain Man", "");UserAddEventArgs args = new UserAddEventArgs(user);if (UserAddEvent != null) {this.UserAddEvent(this, args);}}
}

3.1.1. 自定义事件参数类:UserAddEventArgs

自定义的事件参数类“UserAddEventArgs”必须继承自“EventArgs”类,在此基础上添加了public成员“AddedUser”

3.1.2 定义委托:UserAddEventHandler

  • 注意该委托的参数类型,第二个参数为“自定义的事件参数”。
  • 该委托用于在“FrmMain”窗体中实例化,实例化后绑定事件处理函数“OnUserAdd”。

3.1.3 定义事件变量:UserAddEvent

“UserAddEvent”变量可以理解为“UserAddEventHandler”委托的一个实例化对象,即

public UserAddEventHandler UserAddEvent;    // 在该示例中把"event"修饰符去掉也是可以的

3.2 FrmMain窗体

public partial class FrmMain : Form {// UserAddEvent事件绑定的处理函数private void OnUserAdd(object sender, FrmUserAdd.UserAddEventArgs e) {MessageBox.Show(e.AddedUser.username);}private void btnAdd_Click(object sender, EventArgs e) {FrmUserAdd frm = new FrmUserAdd();FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);frm.UserAddEvent += dele_fn;frm.ShowDialog();}
}

3.2.1 FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);

dele_fn为“UserAddEventHandler”的一个实例(指针),它指向事件处理函数“OnUserAdd”

3.2.2 frm.UserAddEvent += dele_fn;

可以看出此处实际就是“多路广播”,同时也可以看出“UserAddEvent”事件变量实际就是“UserAddEventHandler”委托的一个实例。

3.3 执行逻辑

该示例看似复杂,其实质是将本在“一个窗体”中的实现,拆成了“两个窗体”。下面将两个窗体的代码合成“一个窗体”

public partial class FrmUserAdd : Form {// 定义事件参数public class UserAddEventArgs : EventArgs {public User AddedUser;public UserAddEventArgs(User user) {this.AddedUser = user;}}// 定义委托,并指定参数类型public delegate void UserAddEventHandler(object sender, UserAddEventArgs e);// 定义事件,并指定该事件的“委托”public UserAddEventHandler UserAddEvent;
    public event UserAddEventHandler UserAddEvent;// UserAddEvent事件绑定的处理函数private void OnUserAdd(object sender, FrmUserAdd.UserAddEventArgs e) {MessageBox.Show(e.AddedUser.username);}private void btnOK_Click(object sender, EventArgs e) {User user = new User(1, "Rain Man", "");UserAddEventArgs args = new UserAddEventArgs(user);FrmUserAdd.UserAddEventHandler dele_fn = new FrmUserAdd.UserAddEventHandler(OnUserAdd);this.UserAddEvent += dele_fn;if (UserAddEvent != null){this.UserAddEvent(this, args);}}
}

C#:委托和自定义事件相关推荐

  1. C# 窗体间传值(使用委托与自定义事件)

    using System; using System.Drawing; using System.Windows.Forms; namespace 跨窗体调用控件 { public partial c ...

  2. C#事件-自定义事件

    事件有很多,比如说 鼠标的事件:MouserMove,MouserDown等. 键盘的事件:KeyUp,KeyDown,KeyPress. 有事件,就会有对事件进行处理的方法,而事件和处理方法之间是怎 ...

  3. 浅析C#的事件处理和自定义事件

    一.简单的自定义事件(1):无参数 namespace UserInputMonitor { class UserInputMonitor { public delegate void UserReq ...

  4. c#自定义事件的使用方法

    c#自定义事件 1.声明一个委托类  public delegate SomethingChangedHandler(object sender,EventArgs e); 2.在你的类中声明一个事件 ...

  5. 通过c# 实现自定义属性改变触发自定义事件 ,理解自定义事件及其触发过程

    以下说明可解释自定义的事件的自定义触发过程: 直接上代码,内含说明(界面是两个文本框textbox1,textbox2,和一个button1,界面的Load事件,button的click事件) For ...

  6. C# 自定义事件(EventArgs)

    1,自定义事件: public class TextChangeEventArgs : EventArgs { private string message; public TextChangeEve ...

  7. python实现回调函数,自定义事件

    最近一个项目,需要实现自定义事件,发现python对于事件好像没有一个非常标准的封装,或者是原语,下面是自己去实现的一个类似事件的方法,逻辑上参考了.net实现事件的方法,也就是特殊的委托. 1. p ...

  8. Vue组件绑定自定义事件

    Vue组件使用v-on绑定自定义事件: 可以分为3步理解: 1.在组件模板中按照正常事件机制绑定事件: template: '<button v-on:click="increment ...

  9. cocos2d-js 自定义事件监听派发

    熟悉js的dom事件或者flash事件的,基本都能立马明白cc.eventManager的用法. cc.eventManager有两种注册监听器的方式,一种是原生事件,例如 cc.eventManag ...

最新文章

  1. 怎么学python-如何高效学 Python?
  2. DEV—【GridControl添加按钮列】
  3. apt-get无法下载,一些网址Not Found 404
  4. eprom是计算机内存吗,存储器EPROM的应用
  5. 利用snmptools实现cacti自定义监控Windows性能计数器
  6. linux18.2安装界面,Ubuntu 18.10下安装Grub Customizer 5.1.0配置grub2图形化界面
  7. linux系统无root权限lua库安装,liunx系统中安装lua以及torch
  8. php 时间和日期,php日期和时间的应用
  9. (转)Scala中的Some和Option
  10. 在idea中设置java方法自定义注释
  11. G4L---linux系统---硬盘对拷(克隆)
  12. leetcode 225. Implement Stack using Queuesk
  13. javamail 收件人/发件人 乱码解析
  14. 全解电磁流量计功能和精度性能
  15. 经典网络结构分析:卷积神经网络的现代雏形 ---LeNet
  16. ChucK初步(13)
  17. 微信小程序之获取当前位置附近的美食、酒店、娱乐、超市等,并显示标记
  18. 一文搞定 JVM 面试,教你吊打面试官~
  19. hdu5761Rower Bo(计算几何)
  20. QQ秀已然式微,而同时迭代的厘米秀正在雄起。

热门文章

  1. python怎么导入txt文件夹-python读取一个目录下所有txt里面的内容方法
  2. python推荐系统-RecQ-Python推荐系统框架
  3. python基础语法手册format-python基础_格式化输出(%用法和format用法)
  4. python语法syntaxerror怎么修改-Python 语法错误
  5. python语言入门m-python基础入门这一篇就够
  6. UVa12467 Secret Word(kmp)
  7. LeetCode Longest Substring with At Least K Repeating Characters(递归)
  8. linux下查看监听端口对应的进程
  9. 【OO学习】OO第四单元作业总结及OO课程总结
  10. luoguP2657 [SCOI2009]windy数