事件--c#

以上是事件的几个操作。

事件由五个组件构成:

具体作用如下:

事件声明:

event  委托类型 事件名;例子:

public event EventHandler Elapsed;

还可同时声明几个事件:

public event EventHandler    Event1,Event2,Event3;

还可添加static使得事件静态。

事件说明

事件是成员,不是类型,所以不能通过new来创建他的对象。

由于是成员:

1,他必须声明在类或者结构中,和其他成员一样。

2,不能在一段可执行代码中声明事件。

委托类型和eventhandler。

事件必须要有委托类型,我们可以声明一个委托类型或者使用一个已经存在的。

如果声明一个类型,必须指定方法保存的签名和返回类型。

更好的办法是,使用eventhandler。

public delegate void Eventhandler(Object obj,EventArgs e);

事件触发

事件触发和委托一样,都是:事件名(参数,参数);

触发事件必须先判断事件是否null,确认有方法可以执行。 

例如:

if(Elapsed!=null)
    Elapsed(sourse,args);

把事件声明和触发事件代码放在一起,便有了如下发布者类声明。该代码保护两个成员,事件和一个叫onOneSecond()方法。它触发了事件。

public class MyTimerClass
   {
       public event EventHandler Elapse;
        private void onOneSecond(object obj,EventArgs args)
       {
            if(Elapse!=null)
                Elapse(obj,args); //发起事件。
       }
       //下面的代码确认每1秒调用一次onOneSecond()方法。
   }

记住两点:

1)发布者类有一个作为成员的事件,

2)类包含了触发事件的代码。

事件订阅方式:

要为事件添加事件处理程序,处理程序必须和委托有一样返回值类型和签名。

使用+=运算符为事件增加事件处理程序。

方法可以是下面任何一个:

1)实例方法  2)静态方法  3)匿名方法  4)lambda表达式。

下面代码为Elapsed事件增加三个方法。

类        

mc.Elapsed+=ca.TimerHandlerA;   实例方法

mc.Elapsed+=classB.TimerHandlerB;  静态方法

mc.Elapsed+=new EventHandler(cc.TimerHandlerC);  委托形式。

和委托一样,我们可以使用匿名方法和lambda表达式来增加事件处理程序。例如,如下代码先使用lambda表达式后使用了匿名方法。

            mc.Elapsed+=(source,args)=>
                {
                    Console.WriteLine("lambda expression");
                }
            mc.Elapsed+=delegate(object source,EventArgs args)
            {
                Console.WriteLine("anonymous method");
            }

如下程序使用了他之前定义的MyTimerClass类。

1)他从两个不同实例注册两个事件处理程序。

2)注册事件后休眠2秒,这段时间计时器会触发两次事件,两个事件每次都会执行。

 

事件移除程序:

使用-=符合移除事件处理。

MC.Elapsed-=CA.TimerHandlerA;

标准事件用法

事件使用标准模式的跟本是eventhandler委托类型。eventhandler委托类型的声明如下代码所示:

1)第一个参数用来保存触发事件的对象的引用。由于是object类型,所以可以匹配任何类型的实例。

2)第二个参数保存有关状态用于应用程序来说是否合适的状态信息。

public delegate void eventhandler(object  sender,eventargs e);

eventargs用于传递数据,但是被设计成不能传递任何数据。  

如果你希望传递数据,必须设计一个eventargs继承的类。使用合适的字段保存需要传递的数据。

通过扩展eventargs 来传递数据。

我们需要 声明一个派生自eventArgs的自定义类。类的名称应该以EventArgs结尾

 public class MyTCEventArgs : EventArgs
    {
        public string Message;
        public MyTCEventArgs(string s)
        {
            Message = s;
        }
    }

使用自定义委托

既然有了一个自定义类,就可以传递数据了。我们需要一个委托类型来使用新的自定义类。实现方式如下:

第一种方式是非泛型委托:

1)创建一个自定义委托。

2)在代码的其他部分使用新的委托名称。

public delegate void MyTCEventHandler object sender,MyTCEventArgs e);
            自定义委托名               自定义类

第二种方式是泛型委托:

1)在方括号中放置自定义类。

2)无论哪里使用自定义委托名称,都使用完整的字符串。例如,event声明是这样的:

 public event EventHandler<MyTCEventArgs> Elapsed;
          自定义类的泛型委托      事件名

如下是一种泛型委托实现例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication5
{
    public class MyTCEventArgs : EventArgs  //自定义类声明
    {
        public string Message;
        public MyTCEventArgs(string s)
        {
            Message = s;
        }
    }
    public class MyTimerClass           //事件声明及发起事件的代码
    {
        public event EventHandler<MyTCEventArgs> Elapsed;   //使用泛型委托声明事件
        private void OnOneSecond(object obj, EventArgs e)
        {
            if (Elapsed != null)
            {
                MyTCEventArgs mtcea= 
                new MyTCEventArgs("Message from Onesecond");
                Elapsed(obj, mtcea); //因为事件是EventHandler<MyTCEventArgs>声明的,而EventHandler<MyTCEventArgs>是一个委托类型,所以Elapsed的参数个数跟EventHandler<MyTCEventArgs>一样,
                //转到定义可以看到 public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);有两个参数,所以事件Elapsed也有两个参数,且相互对应。               
            }
        }
    }
    class classA                //事件处理程序
    {
        public void TimerHandlerA(Object obj, MyTCEventArgs e)
        {
            Console.WriteLine("classA message {0}", e.Message);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            classA ca = new classA();
            MyTimerClass mc = new MyTimerClass();

            mc.Elapsed += new EventHandler<MyTCEventArgs>(ca.TimerHandlerA);    //事件注册程序

            Thread.Sleep(3500);

            Console.ReadLine();
        }
    }
}

 这里的OnOneSecond()方法是System.Timer类的方法,会自动隔一段时间被触发运行一次。

posted @ 2016-10-25 16:54  美好的明天  阅读(426)  评论(0编辑  收藏  举报