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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2024 CODEPRJ.COM