本文主要介绍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.Speak Dele_Str dp_Say = new Dele_Str(p.Say); // 实例化委托指向 p.Say Dele_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); // 输出:333 Console.ReadLine(); } }
在Person类中创建了三个函数:Speak、Say、Translate,这三个函数在参数和返回类型上相同,因此可是使用同一个委托(Dele_Str)。
多路委托:使用同一个委托“指向”不同的函数,使这几个函数可以“计算”,其执行逻辑如下:
执行: string str = dp_Speak("Rain Man"); 输出: Speak: Rain Man Say: Rain Man Translate: 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; // 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); } } }
声明:如需转载,请注明来源于www.webym.net并保留原文链接:http://www.webym.net/jiaocheng/728.html