zoukankan      html  css  js  c++  java
  • C#委托和事件

    委托是一种定义方法的类,这样就可以使得方法A,可以像string类、int类一样当做方法B的参数进行传递。这种将方法动态地赋值给参数的做法,可以避免在代码中大量使用if-else(or switch)语句,同时使得程序具有更好的可扩展性。委托被大量使用在WPF中(至少我是这么认为的)。但是委托类不同于string类和int类的区别在于,可以将多个方法赋给同一个委托,或者说多个方法可以绑定到同一个委托类上,当调用该委托时,将依次调用其所绑定的方法,但是string类和int类,后面绑定的参数将会替换掉前一个参数。

    事件用于封装委托类。当使用string类时,可以通过属性对字段进行封装,某个string类可以只读的,也可以是只写的。使用event关键字,声明一个事件也就是声明了一个进行了封装的委托类型变量,比如下面这条代码:

    public event PropertyChangedEventHandler PropertyChanged;

    其中,PropertyChangedEventHandler是一个委托类,event关键字定义了一个封装该委托的PropertyChanged事件。事件封装了委托,那么就可以将方法注册到事件中,当事件发生时,会依次调用注册了该事件的方法。比如在WPF中,给一个button控件添加Click方法,其实就是将Btn_Click方法注册到button控件的Click事件中,即button.Click += Btn_Click.

    .NET Framework中对委托和事件编写的规范:

    • 委托类型的名称都应该以EventHandler结尾;
    • 委托的返回值是void(最好),并接受两个输入参数,一个是Object类,一个EventArgs类(或继承自EventArgs);
    • 事件的命名为委托去掉EventHandler之后剩余的部分;
    • 继承自EventArgs的类型应该以EventArgs结尾;
    • 订阅事件的方法命名,通常为On+事件名。

    Example:这个例子来源于张子阳博客中的例子,我最开始学习委托和事件也是看了这篇博客,所以我的这篇文章算是学习了委托和事件之后的一个整理,目的是加深自己的记忆。张子阳的博客地址如下:

    http://www.tracefact.net/tech/009.html

    http://www.tracefact.net/tech/029.html

    例子是这样的,假设有一台热水器,当加热到指定温度时会提醒用户,则有一个加热方法,还有一个提醒方法。提醒方法要注册加热事件,当温度达到指定值时,调用提醒方法。

    Heater类

    public class Heater
        {
            private int temperature;
            // 定义一个名为BoiledEventHandler的委托类,两个参数,一个object类,一个是继承自EventArgs类的BoiledEventArgs类
            public delegate void BoiledEventHandler(object sender, BoiledEventArgs e);
            // 定义一个封装BoiledEventHandler委托的事件
            public event BoiledEventHandler Boiled;
    
            // 订阅Boiled事件的方法
            protected virtual void OnBoiled(BoiledEventArgs e)
            {
                // 如果有方法注册了该事件,则调用所有注册了该事件的方法
                if (Boiled != null)
                    Boiled(this, e);
            }
    
            // Heater类中有一个加热的方法
            public void BoilWater()
            {
                for (int i = 0; i <= 100; i++)
                {
                    temperature = i;
                    if (i % 10 == 0 && i <=95)
                        Console.WriteLine("Temperature is {0}.", i);
                    if(temperature > 95)
                    {
                        BoiledEventArgs e = new BoiledEventArgs(temperature);
                        OnBoiled(e);
                    }
                }
            }
        }

    Alarm类

    public class Alarm
        {
            public void MakeAlert(object sender, BoiledEventArgs e)
            {
                Heater heater = sender as Heater;
                Console.WriteLine("Alarm : Temperature is {0}.", e.temperature);
            }
        }

    客户端程序

    class Program
        {
            static void Main(string[] args)
            {
                Heater heater = new Heater();
                Alarm alarm = new Alarm();
    
                // 将Alarm中的MakeAlert方法注册到Heater的Boiled事件中
                heater.Boiled += alarm.MakeAlert;
    
                heater.BoilWater();
    
                Console.Read();
            }
        }

     源代码github地址:

    https://github.com/Larissa1990/DelegateExample

  • 相关阅读:
    [Typescript] Augmenting Modules with Declarations
    [Postgres] On conflict Do Something Clause in Postgres
    [React] Debug Custom React Hooks With useDebugValue
    为什么不推荐通过Executors直接创建线程池
    JAVA线程池使用注意事项
    Java线程池使用的注意事项
    分布式事务(六)总结提高
    分布式事务(五)源码详解
    分布式事务(三)mysql对XA协议的支持
    分布式事务(二)Java事务API(JTA)规范
  • 原文地址:https://www.cnblogs.com/larissa-0464/p/10637353.html
Copyright © 2011-2022 走看看