您的位置:首页 > 移动开发 > Objective-C

事件(event)与委托(delegate)

2006-12-28 09:56 363 查看
  事件(event)与委托(delegate)
1.谈谈函数指针
   一个函数在编译时被分配给一个入口地址。这个入口地址就称为“函数的指针”。用一个指针变量指向函数,然后通过该指针变量调用此函数,这个指针变量就称为“指向函数的指针”。


void Main()






{


  int Max(int,int);


  //声明一个函数指针


  int (*p)(int,int);


  int a,b,c;


  //



  //把Max函数的入口地址赋给指针变量p


  p=Max;


  //函数指针的形式调用Max函数


  c=(*p)(a,b);


}
   下面我们再来看看回调函数:
   如果给p赋不同的值(不同的函数地址),那么调用者就能调用不同的函数;赋值可以发生在运行时,从而实现动态绑定。这里的调用者即我们要谈的回调函数。


int Main()






{


  int Max(int,int);


  int Min(int,int);


  //



  int (*p)(int,int);


  //p=Min;


  p=Max;


  //传递函数地址给调用者


  Caller(p);


}




//回调函数


void Caller(int (*ptr)(int,int))






{


  //调用ptr指向的函数


  ptr();


}
      
2.什么是委托
   
以下内容来自:http://www.cnblogs.com/WuCountry/archive/2006/11/29/576030.html
   先来看下面的代码:


using System;


namespace ConsoleApplication1






{


    class Class1




    

{


        [STAThread]


        static void Main(string[] args)




        

{


            bool m_isRight = false;


            object m_obj = m_isRight?MyWrite("true"):MyWrite("false");


            Console.Write(m_obj);


        }


        static private int MyWrite(object i_string)




        

{


            Console.Write(i_string);


            return i_string.ToString().Length;


        }


    }


}



   如果认为Console.Write(m_obj);等于是Console.Write(MyWrite("false"));这显然不对!
   如果真要给m_obj对象赋予函数MyWrite(),会怎么样呢?
   把函数当成变量赋给对象,我们首先得解决三个问题:
   1、如果可以对一个对象赋函数值,如何区别不同的函数;
   2、如何给这个对象赋函数值;
   3、如何用这个对象调用原来的函数;
   对于第一个问题,首先我们应认识到c#中是可以对一个对象赋函数值的;解决这个问题的办法是先对该对象声明,声明它可以被什么样的函数来赋值,而这个对象声明在C#里的学名就是委托[/u]。这和上面讲到的函数指针十分类似(其实委托的内部机制比函数指针复杂的多)。
   现在我们可以声明如下的委托来解决问题一:


delegate int MyDelegate(object i_object);


//


MyDelegate m_delegate = new MyDelegate(MyWrite);


//MyWrite函数如下,它是满足委托的申明的。


                   static private int MyWrite(object i_string)




                   

{


                            Console.Write(i_string);


                            return i_string.ToString().Length;


                   }
   委托声明:MyDelegate m_delegate = new MyDelegate(与MyDelegate申明一致的函数名);
   这样就完美的解决了第一个问题。
   OK,第二个问题。如何给这个对象m_delegate赋函数值?其实上面在实例化委托对象时,已经对其赋值MyWrite,因此它已经具有了MyWrite函数的功能。只有这种方法对其进行赋值么?不,另一种赋值形式就是事件。
   我们再来看第三个问题,这个问题看下面的代码就清楚了:


using System;


namespace ConsoleApplication1






{


    class Class1




    

{


        //先申明一个委托对象。


        delegate int MyDelegate(object i_object);


        [STAThread]


        static void Main(string[] args)




        

{


            MyDelegate m_delegate = new MyDelegate(MyWrite);


            m_delegate("This is a delegate object to call the raw function.");


        }


        //该函数是满足上面委托对象的申明的。


        static private int MyWrite(object i_string)




        

{


            Console.Write(i_string);


            return i_string.ToString().Length;


        }        


    }


}



3.事件与事件委托 
   事件是对象发送的消息,以发信号通知操作的发生。操作可能是由用户交互(例如鼠标单击)引起的,也可能是由某些其他的程序逻辑触发的。引发事件的对象称为事件发送方。捕获事件并对其作出响应的对象叫做事件接收方。(MSDN)
   事件是基于委托的,而由上面的定义可以知道我们将要遇到的问题是:
   1、如何动态的(运行时)对“特殊委托”赋函数值,怎样实现?
   2、运行时,如何知道“特殊委托”已经被赋过值及如何赋值?
   3、能否在“特殊委托”上添加多个函数值?如果可以,如何删除?

   相信大家已经知道这个“特殊委托”就是我们要谈的事件。来看一下它的声明:
   public event MyDelegate m_myevent;//声明事件(第一个问题)
   public MyDelegate m_mydelegate;//声明委托
   是不是很像?我们来看看它们的区别:
   1、事件不能直接把函数当值一样赋给它的委托;而委托可以直接赋函数;
  2、事件只能把一个实例的委托当值赋给它;也就是说事件是用来管理委托的,进而管理函数。因为一个实例化的委托肯定有一个函数与之对应。
  3、在一个事件上可以动态添加或删除委托;而委托上不能动态添加或删除函数。
  OK,我们来看看第二个问题。如何赋值?它的赋值有点怪:
  m_myevent += m_mydelegate;
  这里也正好说明了事件是动态管理委托的。
  那么又如何删除?m_myevent -= m_mydelegate;没有委托的情况下可以删除么?答案是肯定的。
  最后看一个完整的例子(从中可以知道如何判断事件是否已赋过值):
 


using System;


namespace ConsoleApplication1






{


    class Class1




    

{


        //先声明一个委托对象。


        delegate int MyDelegate(object i_object);


        //声明一个事件对象


        static event MyDelegate m_myevent;


        [STAThread]


        static void Main(string[] args)




        

{


            //实例化委托


            MyDelegate m_delegate = new MyDelegate(MyWrite);


            m_delegate("This is a delegate object to call the raw function.");


            //实例化的委托赋值给事件


            m_myevent += m_delegate;


            m_myevent += new MyDelegate(MyWrite);


            m_myevent +=new MyDelegate(Class1_m_myevent);


            //判断事件是否已赋过值


            if(m_myevent!=null)




            

{


                m_myevent("This is a event to call the funcaion on the delegate.");


            }            


        }


        //该函数是满足上面委托对象的申明的。


        static private int MyWrite(object i_string)




        

{


            Console.WriteLine(i_string);


            return i_string.ToString().Length;


        }




        private static int Class1_m_myevent(object i_object)




        

{


            Console.WriteLine(i_object);


            return 0;


        }


    }


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息