浅谈c#中的委托和事件

      大学扩招后,各类大学或学院如牛毛般兴起。随之而产生的现象是大学生源质量的下降,而优质大学老师也是僧多粥少,必然使大量水平尚不达标的教师混入各类院校,使上课的精彩程度有所降低。于是,逃课的学生们也越来越多...

      作为众多大学生中一员的本文作者,也混迹在某所二流学校里。

      某天上课铃响后,授课老师拿着《管理信息系统》一书讲课到一半,眼睛一描台下寥寥无几昏昏欲睡的几个“好”学生,脸上泛起阴沉的笑容,”我们来点名吧!没到的举手!“这话乍一出口,台下便一片大乱,美女班长急匆匆拿起手机,快速按着键盘编辑短信催逃课的同学来上课。

      本文的作者作为当时在场的一员,目睹当今大学课堂之怪状,脑中立即浮现出本程序的雏形。

      首先,我们分别以三个类Teacher,Monitor,Student表示教师,班长,逃课同学,其中教师有一个点名方法,班长有个发短信通知逃课同学来上课的方法,逃课同学则有个方法表示回复班长短信通知。

      接着,我们在Teacher类中定义一个委托和与之对应的事件,分别如下:

public  delegate  void signHandler( bool param);
public  event signHandler sign;

     再为Teacher类添加一个私有变量,该变量用以指示教师是否已点名。

private  bool isSigned;

     最后是为Teacher类增加一个点名方法,方法的具体实现请看代码

public  void SignName()
{
  Console.WriteLine(
" 我是老师:不来上课?后果很严重! " );
  
this .isSigned = true ;
  
// 触发点名事件
  if (sign != null )
  {
    sign(isSigned);
  }
}

     至此,Teacher类全部完成。而代表班长的Monitor类与Teacher类非常类似,它有一个sendHandler委托,和封装该委托的表示发通知短信的send事件。最后Monitor类还有一个SendSMS方法,它表示班长发通知短信的动作。具体实现参见代码

class Monitor
{
  
public  delegate  void sendHandler( bool param);
  
public  event sendHandler send;
  
// 表示班长是否已发通知短信的私有字段
  private  bool isSent;
  
// 班长看到教师点名后发短信通知没来同学
  public  void SendSMS( bool param)
  {
    
if (param)
    {
      Console.WriteLine(
" 我是班长:老师点名了,快来上课,不来期末不给过! " );
      
this .isSent = true ;
      
// 触发发短信事件
      if (send != null )
      {
        send(isSent);
      }
    }
  }
}

     到此为止,大部分工作都已完成。最后出场的是表示逃课学生的Student类,该类实现非常简单,只有一个GoToClass方法,表示该学生收到班长通知短信后回复短信并赶去课室。

class Student
{
  
// 学生收到班长短信后去上课
  public  void GoToClass( bool param)
  {
    
if (param)
    {
      Console.WriteLine(
" 我是学生:报告班长,短信已收到,正赶来上课! " );
    }
  }
}

      最后,我们来看下主程序如何实现。先分别构造教师,班长,学生的实例,再将Monitor类的SendSMS方法注册到Teacher类的sign事件上,这样做表示了班长的发短信方法订阅了教师的方法,教师一点名即触发sign事件,此时班长立刻会心的传短信通知未到学生来上课。

      接着我们还要将逃课学生的GoToClass方法注册到班长的send事件上,班长发短信表示教师点名了,逃课学生只得乖乖的赶去上课,学分为大嘛。

class Program
{
  
static  void Main( string [] args)
  {
    Teacher teacher
= new Teacher();
    Monitor monitor
= new Monitor();
    Student student
= new Student();
    
// 班长的发短信方法订阅教师的点名事件
    teacher.sign += new Teacher.signHandler(monitor.SendSMS);
    
// 学生的上课方法订阅班长的发短信事件
    monitor.send += new Monitor.sendHandler(student.GoToClass);
    teacher.SignName();
  }
}
 
完整版DEMO如下:
namespace delegateDEMO
{
  
class Teacher
  {
    
public  delegate  void signHandler( bool param);
    
public  event signHandler sign;
    
// 表示教师是否已点名的私有字段
    private  bool isSigned;
    
// 教师点名
    public  void SignName()
    {
      Console.WriteLine(
" 我是老师:不来上课?后果很严重! " );
      
this .isSigned = true ;
      
// 触发点名事件
      if (sign != null )
      {
        sign(isSigned);
      }
    }
  }

  
class Monitor
  {
    
public  delegate  void sendHandler( bool param);
    
public  event sendHandler send;
    
// 表示班长是否已发通知短信的私有字段
    private  bool isSent;
    
// 班长看到教师点名后发短信通知没来同学
    public  void SendSMS( bool param)
    {
      
if (param)
      {
        Console.WriteLine(
" 我是班长:老师点名了,快来上课,不来期末不给过! " );
        
this .isSent = true ;
        
// 触发发短信事件
        if (send != null )
        {
          send(isSent);
        }
      }
    }
  }

  
class Student
  {
    
// 学生收到班长短信后去上课
    public  void GoToClass( bool param)
    {
      
if (param)
      {
        Console.WriteLine(
" 我是学生:报告班长,短信已收到,正赶来上课! " );
      }
    }
  }

  
class Program
  {
    
static  void Main( string [] args)
    {
      Teacher teacher
= new Teacher();
      Monitor monitor
= new Monitor();
      Student student
= new Student();
      
// 班长的发短信方法订阅教师的点名事件
      teacher.sign += new Teacher.signHandler(monitor.SendSMS);
      
// 学生的上课方法订阅班长的发短信事件
      monitor.send += new Monitor.sendHandler(student.GoToClass);
      teacher.SignName();
    }
  }
}

    程序运行的结果如下:

     写在最后:也许有的朋友看完上面的例子后,会觉得程序中的委托和事件形式与webform和winform中的形式有很大区别,比如winform中常见的按钮单击,其委托和事件的定义分别如下

public  delegate  void EventHandler( object sender, EventArgs e);
public  event EventHandler Click;

     而我们在界面上双击按钮后,进入后台代码中的Click方法如下

private  void button1_Click( object sender, EventArgs e)
{
  MessageBox.Show(
" Hello World! " );
}

     由此我们可以得知.net framework中委托和事件的编码规范有以下几条:

  • 委托类型名称以EventHandler结束。
  • 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object类型,表示事件源,一个EventArgs类型(或继承自EventArgs),表示事件参数。
  • 事件类型名称为委托去掉EventHandler之后剩余的部分。
  • 继承自EventArgs的类型应该以EventArgs结尾。
  • 订阅事件的方法的命名,通常为“On+事件名”

    知道规范后,我们再来看看根据该规范对上述程序的修改

namespace NormalizeDelegateDemo
{
  
public  class Teacher
  {
    
public  delegate  void SignEventHandler( object sender, SignEventArgs e);
    
public  event SignEventHandler Sign;
    
// 表示教师是否已点名的私有字段
    private  bool isSigned;
    
public  class SignEventArgs : EventArgs
    {
      
public  readonly  bool isSigned;
      
public SignEventArgs( bool issigned)
      {
        
this .isSigned = issigned;
      }
    }
    
public  void OnSign(SignEventArgs e)
    {
      
if (Sign != null )
      {
        Sign(
this , e);
      }
    }
    
// 教师点名
    public  void SignName()
    {
      Console.WriteLine(
" 我是老师:不来上课?后果很严重! " );
      
this .isSigned = true ;
      
// 触发点名事件
      SignEventArgs e = new SignEventArgs(isSigned);
      OnSign(e);
    }
  }

  
public  class Monitor
  {
    
public  delegate  void SendEventHandler( object sender,SendEventArgs e);
    
public  event SendEventHandler Send;
    
// 表示班长是否已发通知短信的私有字段
    private  bool isSent;
    
public  class SendEventArgs : EventArgs
    {
      
public  readonly  bool isSent;
      
public SendEventArgs( bool issent)
      {
        
this .isSent = issent;
      }
    }
    
public  void OnSend(SendEventArgs e)
    {
      
if (Send != null )
      {
        Send(
this ,e);
      }
    }
    
// 班长看到教师点名后发短信通知没来同学
    public  void SendSMS( object sender,Teacher.SignEventArgs e)
    {
      
if (e.isSigned)
      {
        Console.WriteLine(
" 我是班长:老师点名了,快来上课,不来期末不给过! " );
        
this .isSent = true ;
        
// 触发发短信事件
        SendEventArgs _e = new SendEventArgs(isSent);
        OnSend(_e);
      }
    }
  }

  
public  class Student
  {
    
// 学生收到班长短信后去上课
    public  void GoToClass( object sender,Monitor.SendEventArgs e)
    {
      
if (e.isSent)
      {
        Console.WriteLine(
" 我是学生:报告班长,短信已收到,正赶来上课! " );
      }
    }
  }

  
public  class Program
  {
    
static  void Main( string [] args)
    {
      Teacher teacher
= new Teacher();
      Monitor monitor
= new Monitor();
      Student student
= new Student();
      
// 班长的发短信方法订阅教师的点名事件
      teacher.Sign += new Teacher.SignEventHandler(monitor.SendSMS);
      
// 学生的上课方法订阅班长的发短信事件
      monitor.Send += new Monitor.SendEventHandler(student.GoToClass);
      teacher.SignName();
    }
  }
}

     好了,整篇文章也到了结束的时候。最后我们再来回顾下结论:链接到委托上的方法必须具有与委托相同的方法签名,委托可以代表一类特定方法签名的方法,它的功能类似于C++中的方法指针。而与委托相应的事件则为委托提供了封闭与包装。

 

 

转载于:https://www.cnblogs.com/tudas/archive/2011/04/30/delegate.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值