zoukankan      html  css  js  c++  java
  • 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;
        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);
            }
        }
    }
  • 相关阅读:
    网络优化改进
    图像识别和卷积神经网路案例的实现
    卷积神经网络和图像识别
    ANA网络分析
    大数阶乘
    HDU 1002 A + B Problem II (大数加法)
    HDU 1232 畅通工程 (并查集)
    HDU 1231 最大连续子序列 (dp)
    HDU 2546 饭卡 (dp)
    HDU 1203 I NEED A OFFER! (dp)
  • 原文地址:https://www.cnblogs.com/rainman/p/3650925.html
Copyright © 2011-2022 走看看