现在的位置: 首页 > 综合 > 正文

Event

2013年02月27日 ⁄ 综合 ⁄ 共 2355字 ⁄ 字号 评论关闭

事件处理时组件设计中相当重要的一环,在C#事件与delegate是紧密相关的,下面是一个简单的事件范例。

1-1

using System;
namespace EventDemo
{
   public delegate void ProcessHander(object sender);
   public class Class1
   {
       private event ProcessHandler processHandler = null;
       public event ProcessHandler ProcessStart
       {
          add{
            processHandler +=value;
          }
          remove{
             processHandler -=value;
          }
       }
       
       public void Process()
       {
           processHander(this);
           for(int i=0;i<10;i++)
           {
               i=i+1;
           }
       }

       public Class1(){}
   }
}

C#之中的delegate扮演者函数指针的角色,用户可以将某个函数加入一个delegate之中,而一个delegate允许用户加入一个以上的函数,当调用此delegate时就等同于调用其内所含的所有函数。不过程序的设计手法潜藏着一个问题,就是当事件数众多时,对象就必须付出相应数量的delegate变量,如下面程序:

1-2

private event ProcessHandler processStart = null;
private event ProcessHandler processEnd =null;
private event ProcessHandler ProcessStep =null;

不管用户是否用到了这些事件,当对象被创建起来时就得付出这些成本,这在窗口应用程序上更显得可怕,因为Window Message(窗口消息)的数量以千为单位,假如一个简单的窗口程序就必须付出相对于Windows Message数量的变量成本,这样一来对象岂不成了庞然大物了。

针对这个问题,.net framework采取了与Lazy-Allocate类似的方式来处理,如下面程序

 

public class Class1
{

   private Hashtable eventList = new Hashtable();
   private static object processStart = new object();
   private static object processEnd = new object();
   
   public event ProcessHandler ProcessStart
   {
     add{
       eventList.Add(processStart,value);
     }
     remove{
       eventList.Remove(processStart);
     }
   }
   public event ProcessHandler ProcessEnd
   {
     add{
       eventList.Add(processEnd,value);
     }
     remove{
       eventList.Remove(processEnd);
     }
   }

   public void Process()
   {
     ProcessHandler start = (ProcessHandler)eventList[processStart];
     ProcessHnadler end = (ProcessHandler)eventList[processEnd];
     if(start!=null) start(this);   
     for(int i =0 ;i<10;i++)   
     {
       i = i+1;
     }
     if(end!=null) end(this);
   }
 }

程序中声明了一个Hashtable类型的对象:eventList,每一个Class1类的实体都拥有这个对象,另外还声明了两个objec类型的对象:processStart、processEnd,注意!这两个对象是static(静态)类型,也就是说,不管有多少个对象实体,都只须花费两个object的空间。那这段代码与上面的做法有何不同呢?答案是对象所占的内存大小不同,当用户创建一个对象实体后,此对象占用了一个Hashtable对象的内存空间,在用户设定了ProcessStart事件时,此对象随之占用了一个Hashtable元素的内存空间,若用户未设定事件,那么次元素的内存空间就不会被占用,相较于前面范例的预付行为,此方式可以省下不必要付出的内存成本。再详细点说,假设Class1拥有1000个事件,那么程序1-2的做法在对象创建初期就会占用1000个event变量的内存空间,而程序1-3则要付出一个Hashtable对象及1000个static变量的代价,当用户创建第二个对象时,程序1-2要再次占用了1000个event变量的代价,但程序1-3只须占用一个hashtable对象的代价,优劣立见不是吗?很幸运,这种设计概念在.net
framework中已提供了基础建设,设计人员要套用即可,见下面程序1-4:

public class Componet1:Componet
{
   private static object processStart = new object();
   public event EventHandler ProcessStart
   {
      add{
        Events.AddHandler(processStart,value);
     }
      remove{
         Events.RemoveHandler(processStart,value);
     }
   }
   public void Process()
   {
      EventHandler handler = (EvnetHandler)Events[processStart];
      if(handler !=null)
        handler(this,null);
   }
}

只要继承自Component类或其子类就可以使用这种方式来处理事件。

 

 

抱歉!评论已关闭.