C#:委托和自定义事件
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#:委托和自定义事件相关推荐
- C# 窗体间传值(使用委托与自定义事件)
using System; using System.Drawing; using System.Windows.Forms; namespace 跨窗体调用控件 { public partial c ...
- C#事件-自定义事件
事件有很多,比如说 鼠标的事件:MouserMove,MouserDown等. 键盘的事件:KeyUp,KeyDown,KeyPress. 有事件,就会有对事件进行处理的方法,而事件和处理方法之间是怎 ...
- 浅析C#的事件处理和自定义事件
一.简单的自定义事件(1):无参数 namespace UserInputMonitor { class UserInputMonitor { public delegate void UserReq ...
- c#自定义事件的使用方法
c#自定义事件 1.声明一个委托类 public delegate SomethingChangedHandler(object sender,EventArgs e); 2.在你的类中声明一个事件 ...
- 通过c# 实现自定义属性改变触发自定义事件 ,理解自定义事件及其触发过程
以下说明可解释自定义的事件的自定义触发过程: 直接上代码,内含说明(界面是两个文本框textbox1,textbox2,和一个button1,界面的Load事件,button的click事件) For ...
- C# 自定义事件(EventArgs)
1,自定义事件: public class TextChangeEventArgs : EventArgs { private string message; public TextChangeEve ...
- python实现回调函数,自定义事件
最近一个项目,需要实现自定义事件,发现python对于事件好像没有一个非常标准的封装,或者是原语,下面是自己去实现的一个类似事件的方法,逻辑上参考了.net实现事件的方法,也就是特殊的委托. 1. p ...
- Vue组件绑定自定义事件
Vue组件使用v-on绑定自定义事件: 可以分为3步理解: 1.在组件模板中按照正常事件机制绑定事件: template: '<button v-on:click="increment ...
- cocos2d-js 自定义事件监听派发
熟悉js的dom事件或者flash事件的,基本都能立马明白cc.eventManager的用法. cc.eventManager有两种注册监听器的方式,一种是原生事件,例如 cc.eventManag ...
最新文章
- 怎么学python-如何高效学 Python?
- DEV—【GridControl添加按钮列】
- apt-get无法下载,一些网址Not Found 404
- eprom是计算机内存吗,存储器EPROM的应用
- 利用snmptools实现cacti自定义监控Windows性能计数器
- linux18.2安装界面,Ubuntu 18.10下安装Grub Customizer 5.1.0配置grub2图形化界面
- linux系统无root权限lua库安装,liunx系统中安装lua以及torch
- php 时间和日期,php日期和时间的应用
- (转)Scala中的Some和Option
- 在idea中设置java方法自定义注释
- G4L---linux系统---硬盘对拷(克隆)
- leetcode 225. Implement Stack using Queuesk
- javamail 收件人/发件人 乱码解析
- 全解电磁流量计功能和精度性能
- 经典网络结构分析:卷积神经网络的现代雏形 ---LeNet
- ChucK初步(13)
- 微信小程序之获取当前位置附近的美食、酒店、娱乐、超市等,并显示标记
- 一文搞定 JVM 面试,教你吊打面试官~
- hdu5761Rower Bo(计算几何)
- QQ秀已然式微,而同时迭代的厘米秀正在雄起。
热门文章
- python怎么导入txt文件夹-python读取一个目录下所有txt里面的内容方法
- python推荐系统-RecQ-Python推荐系统框架
- python基础语法手册format-python基础_格式化输出(%用法和format用法)
- python语法syntaxerror怎么修改-Python 语法错误
- python语言入门m-python基础入门这一篇就够
- UVa12467 Secret Word(kmp)
- LeetCode Longest Substring with At Least K Repeating Characters(递归)
- linux下查看监听端口对应的进程
- 【OO学习】OO第四单元作业总结及OO课程总结
- luoguP2657 [SCOI2009]windy数