Fork me on GitHub

【原创】委托和事件

委托和事件

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

一.委托

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

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

posted @ 2013-03-04 16:04  种花生的读书人  阅读(2025)  评论(3编辑  收藏  举报

该博客仅作为记录笔记,转载随意