事件(event)与委托(delegate)

   事件(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 #里的学名就是委托。这和上面讲到的函数指针十分类似(其实委托的内部机制比函数指针复杂的多)。
   现在我们可以声明如下的委托来解决问题一:
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;
        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值