zoukankan      html  css  js  c++  java
  • 【原创】委托和事件

    委托和事件

    这两天重新温习了一下关于委托和事件方面的知识,总结一下。

    一.委托

    委托就是能够将方法作为变量来传递。

    C#中使用委托的具体步骤是:

    (1)委托的声明。其参数形式一定要和想要包含的方法的参数形式一致。委托可以在程序运行时调用不同的方法,只要这个方法签名和委托签名保持一致。

    格式:

    [修饰符]  delegate  返回类型   委托号(参数列表)

    例如:  

     public delegate void MyDelegate1(string input);//无返回值 有参数
    public delegate double MyDelegate2();//无参数

    声明一个委托的对象,与声明一个普通类对象的方式一样。

     MyClass1 cls = new MyClass1();
                MyDelegate1 d1;
     d1 = new MyDelegate1(cls.dMethod1);
     MyDelegate1 d2 = new MyDelegate1(d1);
     MyDelegate2 d3 = new MyDelegate2(cls.dMethod3);

    委托名    委托对象;

    (2)定义所有要定义的方法,其参数形式和第一步中声明的委托对象的参数形式必须相同。

    定义委托相对应的方法:

           public void dMethod1(string input)
            {
                Console.WriteLine("Method1传递的参数是{0}",input);
            }
            public void dMethod2(string input)
            {
                Console.WriteLine("Method2传递的参数是{0}",input);
            }
            public double dMethod3()
            {
                Console.WriteLine("Method3没有传递的参数");
                return 43.33;
            }

    (3)创建委托对象(将上面写的方法包含其中)

    View Code
    1 MyClass1 cls=new MyClass();  //实例化对象
    2 
    3 MyDelegate d1=new MyDelegate(cls.dMethod1);
    4 
    5 MyDelegate d2=new MyDelegate(cls.dMethod2);
    6 
    7 MyDelegate d3=new MyDelegate(cls.dMethod3);

    (4)通过委托对象调用包含在其中的方法

    d1("你好");
    d2("生活着,学习着!");
    double dbTemp=d3();

    详细实例:

    class MyClass1
        {
            public void dMethod1(string input)
            {
                Console.WriteLine("Method1传递的参数是{0}",input);
            }
            public void dMethod2(string input)
            {
                Console.WriteLine("Method2传递的参数是{0}",input);
            }
            public double dMethod3()
            {
                Console.WriteLine("Method3没有传递的参数");
                return 43.33;
            }
        }
    
    
     class Program
        {
            public delegate void MyDelegate1(string input);
            public delegate double MyDelegate2();
            static void Main(string[] args)
            {
                MyClass1 cls = new MyClass1();
                MyDelegate1 d1;
                d1 = new MyDelegate1(cls.dMethod1);
                d1("3");
                MyDelegate1 d2 = new MyDelegate1(d1);
                d1("daaa");
                d2("dafagd");
                MyDelegate2 d3 = new MyDelegate2(cls.dMethod3);
                d3();
                //委托对象可以封装多个方法,这些方法的集合称为调用列表,使用 + 、+-、 -、 -=
                //运算符向调用列表中增加或移除方法
                MyDelegate1 d4 = d1 + d2;
                d4("1234");
                double dbTemp = d3();
                Console.WriteLine(dbTemp);
                Console.ReadLine();
            }
        }

    二.事件

    (1)事件的声明

    事件是类成员,以关键字event声明。

    格式:

    [修饰符]  event 委托名 事件名;

    所有的事件是通过委托来激活的,其返回值类型一般是void型

    例子: delegate void MyEventHandler();

    class MyEvent
    
    {
    
      public event MyEventHander active;//active就是一个事件名
    
    }

    (2)事件的预定与取消

    事件的预定就是向委托的调用列表中添加方法,是通过事件加上运算符+=来实现的。

    格式:

    事件名+=new 委托名(方法名);

    例如:

    MyEvent evt=new MyEvent();
    evt.active+=new EventHandler(handler);

    在winform窗体中

    OkButton.Click+=new EventHandler(OkButton.Click);

    只要事件被触发,所预定的方法就会被调用。

    事件的取消

    格式:

    事件名 -=new 委托名(方法名);

    OkButton.Click-=new EventHandler(OkButton.Click);

    对于事件的操作只能使用+=和-=这两种运算符。

    (3)事件的发生

     事件的发生就是对事件相对应的委托的调用,也就是委托的调用列表中包含的各个方法的调用。

    格式:

    事件名(参数);

     详细实例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace _02委托和事件01
    {
        class Program
        {
            delegate void MyEventHandler();//为事件建立一个委托
            class MyEvent
            {
                public event MyEventHandler activate;//声明一个事件
                public void Fire()//调用此方法来触发事件
                {
                    if (activate != null)
                    {
                        activate();//事件发生
                    }
                }
            }
            static void Handler()
            {
                Console.WriteLine("事件发生");
            }
            static void Main(string[] args)
            {
                MyEvent evt = new MyEvent();
                evt.activate += new MyEventHandler(Handler);//将方法Handler()添加到事件列表中
                evt.Fire();//调用触发事件的方法
                Console.ReadLine();
            }
        }
    }

    委托的常用格式:

    Delegate void 委托名(object  sender,EventArgs  e);

    总结一下:委托是一个引用方法的对象,当创建一个委托,也就建立了一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所预定的方法。委托是对方法的抽象,它将方法的调用与实现分离,方法的调用者(即委托的执行者)不知道方法的内部如何实现,而方法的实现者也不知道什么时候被调用,委托理所当然成为实现事件的机制。

    错误或者不当之处望各位大神指点

     《续》

    先简要说一下Obsever设计模式

    Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。

    class Program
        {
            static void Main(string[] args)
            {
                Heater heater = new Heater();
                Alarm alarm = new Alarm();
    
                heater.Boiled += alarm.MakeAlarm;//将方法绑定到事件上
                heater.Boiled += (new Alarm()).MakeAlarm;//给匿名对象注册方法
                heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlarm);
                heater.Boiled += Display.ShowMsg;//注册静态方法
    
                heater.BoilWater();//调用烧水这个方法,会自动调用注册过的对象的方法
                Console.ReadLine();
            }
    class Heater
        {
            private int temperature;
            public string type = "RealFire 001";
            public string area = "Made in China ZhengZhou";
            //声明委托
            public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);
            public event BoiledEventHandler Boiled;
            //定义BoiledEventArgs类,传递给Observer所感兴趣的信息
    
            public class BoiledEventArgs : EventArgs
            {
                public readonly int temperature;
                public BoiledEventArgs(int temperature)
                {
                    this.temperature = temperature;
                }
            }
            protected virtual void OnBoiled(BoiledEventArgs e)
           {
               if (Boiled != null)
               {
                   Boiled(this,e);//表示事件的触发者是本身
                }
            }
            public void BoilWater()
            {
                for (int i = 97; i <= 100;i++ )
                {
                    temperature = i;
                    if(temperature>98)
                    {
                        BoiledEventArgs e=new BoiledEventArgs(temperature);
                        OnBoiled(e);
                    }
                }
            }
        }
      class Alarm
        {
            public void MakeAlarm(Object sender,Heater.BoiledEventArgs e)
            {
                Heater heater = (Heater)sender;
                Console.WriteLine("Alarm:{0}--{1}",heater.area ,heater.type);
                Console.WriteLine("Alarm:嘀嘀,水已经{0}度了",e.temperature);
                Console.WriteLine();
            }
        }
    class Display
        {
            public static void ShowMsg(object sender,Heater.BoiledEventArgs e)
            {
                Heater heater = sender as Heater;
                Console.WriteLine("Display:{0}--{1}",heater.area,heater.type);
                Console.WriteLine("DisPlay:水快烧开了,当前温度为:{0}度",e.temperature);
                Console.WriteLine();
            }
        }

     下一篇:事件与委托《续》http://www.cnblogs.com/chenyongblog/archive/2013/04/25/3043605.html

  • 相关阅读:
    php中获取各种路径
    大型网站系统架构演化之路
    404、500、502等HTTP状态码介绍
    Linux 查看进程和删除进程
    mysql中FIND_IN_SET的使用方法
    PHP导出Excel 数字末尾变0或小数点解决办法
    PHP API接口测试小工具
    要慎用mysql的enum字段的原因
    mysql 导入&导出sql文件
    Linux下php安装memcache扩展
  • 原文地址:https://www.cnblogs.com/chenyongblog/p/2942924.html
Copyright © 2011-2022 走看看