事件及其编程方法探讨 事件驱动编程的一般方法

发布时间:2020-02-16 来源: 日记大全 点击:

  摘要:在面向对象编程环境下,对于某种控件都给定了相应的属性及事件(Even),一般用户无法添加属性、事件及其事件驱动程序。在C#语言中,为用户提供了类的属性成员,类属性成员状态的改变,通过事件代理的关联,可以调用相应的事件处理方法。本文介绍C#语言中的属性成员、事件代理的定义,通过事件代理调用事件处理方法等技术,并通过实例程序进行必要的说明。
  关键词:属性;代理;事件;多播事件
  中图分类号:TP312 文献标识码:A
  
  1 事件及基本概念
  
  对于事件(Even),熟悉可视化编程的人员并不陌生。例如,在单击某个“按钮”后,系统应该对此“单击”事件作出相应的反映,如播放一曲MP3乐曲或显示一张图表等。
  在C#语言中,事件的发生可以由用户的操作使然;也可以由程序逻辑触发,例如类的某个对象状态发生改变将引起程序对对象状态的改变并做出相应的处理。触发事件的对象称为事件的发送者,接收事件的对象称为事件的接收者。
  C#语言的事件处理机制具有如下的特征:
  数据成员、方法、事件和属性都是类的一个成员;在.NET框架中,事件是将事件发送者与事件的接收者相关联的一种代理类,也就是事件机制是通过代理实现的。当事件被触发时,由事件的代理通知处理该事件的方法。
  
  2 C#语言中的属性成员
  
  属性常用来封装类的数据,常见的属性有对象名、字体、颜色等。使用属性的好处是使应用程序看起来更加直观。属性的用处是限制外部对类中成员变量的存取访问。
  2.1属性的定义
  C#属性定义的一般格式为:
  class 类名
  { [修饰符] 数据类型 属性名
  {访问函数体}
  }
  其中修饰符可以为:public、private、static、protected、internal、virtual、override、 abstract等。如果修饰符为abstract,则访问函数体只包含“;”,如果是其它修饰符,则访问函数体要包含访问函数体所必须的代码。数据类型表示属性成员值的数据类型。{}中的代码是执行属性过程的程序代码,一般包括get和set两个访问函数体。
  2.2 相关函数的实现
  首先要对包含get和set两个访问函数体的属性进行定义,通过 get 和 set 访问函数将专用数据成员和公共属性关联起来。根据使用情况不同,可以只用get或者set,也可以同时使用get和set。其中,get:用来读取数据成员的值;set:用来设置数据成员的值,其操作往往是“数据成员=value;”。
  2.3 类的属性编程实例
  using System;
  namespace ConAppshuxjuli
  {class point
  { int my_x, my_y ;//定义数据成员
  publicintx //实现属性成员x
  {get{ return my_x;}
   set{ my_x=value;}
  }
  public int y //实现属性成员y
  { get { return my_y;}
  set { my_y = value; }
  }
   }
   class MyApp
   { static void Main(string[] args)
   {point starting = new point();
  point ending = new point();
  //对属性成员赋值
  starting.x = 1;starting.y=3;
  ending.x = 15; ending.y = 17;
  // 对starting.x等属性成员引用
  Console.WriteLine(“起始点坐标是:
  [{0},{1}]”,starting.x,starting.y);
  Console.WriteLine(“终止点坐标是:
  [{0},{1}]”, ending.x, ending.y);
  Console.Read();
  } }}
  上述程序的运行结果为:
  
  3 事件处理程序
  
  事件处理程序编写步骤为:首先要定义一个事件代理,创建包含事件成员的类(事件类),编写事件处理方法,将事件处理方法和事件关联起来等。
  3.1 定义事件代理
  定义事件代理的格式为:
  [修饰符] delegate void 代理名([触发事件的对象,事件参数]\);
  例如:delegate voidCharEventHandler
  (Objectsender, CharEventArgs e);
  关于代理的有关内容可查阅笔者撰写的《代理及其编程方法》一文或其它有关资料。
  3.2 定义一个包含事件信息的类
  定义一个包含事件信息类的格式为:
  public class XXEventArgs:EventArgs
  {//类的具体定义}
  例如:
  public class CharEventArgs:EventArgs
   { public char CurrChar;//字符变量
  public CharEventArgs(char CurrChar)
  { this.CurrChar = CurrChar;}
  ……
  }
  3.3 创建事件类
  创建包含事件成员的类(又称为事件类),首先要定义事件成员,然后编写触发事件的方法或属性等成员。
  (1)定义事件成员的格式为:
   [修饰符] event 事件代理名 事件名
  上述事件代理名必须是在3.1定义事件代理名。
  (2)编写触发事件的方法或属性等成员
  class CharChecker
  {char curr_char;
   //定义事件成员
   public event CharEventHandler CharTest;
   //触发事件的属性
   public char Curr_Char
   { get { return curr_char; }
   set
   { if (CharTest != null)
   { CharEventArgs myevent = new
   CharEventArgs(value);
   //事件成员调用事件处理方法
  CharTest(this, myevent);
   curr_char = myevent.CurrChar;
   } } } }
  3.4 编写事件处理方法
  编写相应的事件处理方法。例如:
  static void Change_X(Object source,
   CharEventArgs e)
  { if(e.CurrChar==?x?|| e.CurrChar
   ==?X?)
   { Console.Write(“触发的字符是x ,”);
  Console.Write(“把 x 替换为:”);
   e.CurrChar =?三?;
  }
  else
   Console.Write(“触发的字符不是x ,”);
  ……
   }
  3.5 事件处理方法和事件相关联
  首先要创建事件类的对象。例如:
  CharChecker chartester = new
   CharChecker();
  再将事件处理方法与事件对象相关联,其格式为:
  事件类对象名.事件成员+=new事件代理名
  (事件处理方法名列表);
  例如:
  chartester.CharTest += new
  CharEventHandler(Change_X);
  3.6 构成完整的事件处理程序实例
  将上述步骤构成的程序代码组合起来就构成一个完整的事件处理程序。
  using System;
  namespace ConEven1
  { //创建包含事件信息的类
  public class CharEventArgs :EventArgs
  { public char CurrChar;//字符变量
  //构造函数
  public CharEventArgs(char CurrChar)
  { this.CurrChar = CurrChar; }
  class CharChecker//创建事件类
  { char curr_char;
  //定义事件成员
  public event CharEventHandler CharTest;
  public char Curr_Char//事件的属性
  { get { return curr_char; }
  set
  { if (CharTest != null)
  { CharEventArgs myevent = new
  CharEventArgs(value);
  //调用事件处理方法 CharTest(this, myevent);
  curr_char = myevent.CurrChar;
  }
  }
  }
  }
  delegate void CharEventHandler
  (bject sender, CharEventArgs e);
  class AppEvent
  { static void Main(string[] args)
  { CharChecker chartester = new
  CharChecker();//创建事件对象
  chartester.CharTest += new
  CharEventHandler(Change_X);
  chartester.Curr_Char = ‘x’;
  Console.WriteLine(“{0}”,
  chartester.Curr_Char);
  chartester.Curr_Char = ‘张’;
  Console.WriteLine(“事件处理的结果:
  {0}”,chartester.Curr_Char);
  Console.Read();
   }
   static void Change_X(Object source,
   CharEventArgs e)
   { if (e.CurrChar == ‘x’ ||
  e.CurrChar== ‘X’)
   { Console.Write(“触发的字符是 x ,”);
   Console.Write(“把 x 替换为:”);
   e.CurrChar = ‘三’;
  }
  else
  Console.Write(“触发的字符不是 x , ”);
   }
  }
   }
  }
  上述程序的执行结果为:
  
  4 多播事件及其程序实现
  
  4.1 多播事件
  多播代理具有创建方法链表的能力,当调用代理时,所有被链接的方法都会被自动调用,也就是多播可以在一次代理调用中调用方法链上的所有方法。创建多播调用链表的方法是:先实例化一个代理,然后使用“+=”运算符把方法添加到调用链表中;也可以使用“-=”运算符从调用链表中删除一个方法。
  事件也可以多播,这一特性可以使多个对象响应事件信息,还可以通过多点传送为一个事件指定多个事件处理方法,加入其它事件处理程序或删除其它处理程序和多重代理方法相同。
  4.2 多播事件处理程序的实现实例
  using System;
  namespace ConEven2
  {//定义事件信息类
   public class CharEventArgs : EventArgs{ public char CurrChar;
   //构造方法
   public CharEventArgs(char CurrChar)
  { this.CurrChar = CurrChar; }
   }
   class CharChecker//定义事件类
   { char curr_char;
  //定义CharEventHandler事件成员CharTest
  public event CharEventHandler CharTest;
   //触发事件的属性
  public char Curr_Char
   { get{ return curr_char; }
   set{ if (CharTest != null)
   { CharEventArgs args=new
  CharEventArgs(value);
  //调用事件代理
   CharTest(this, args);
   curr_char = args.CurrChar;
  }
  }
  }
  }
  //创建一个事件代理
  delegate void CharEventHandler
  (Object sender, CharEventArgs e);
  class AppEvent
  { static void Main()
  { CharChecker chartester=new
  CharChecker();//创建对象
  chartester.CharTest+=new
  CharEventHandler(Change_X);//关联
  chartester.CharTest+=new
  CharEventHandler(Change_Y);//关联
  chartester.Curr_Char = ‘x’;
  Console.WriteLine(“把x替换为:
  {0}”,chartester.Curr_Char);
  chartester.Curr_Char = ‘乙’;
  Console.WriteLine(“事件处理的结果
  :{0}”, chartester.Curr_Char);
  chartester.Curr_Char = ‘y’;
  Console.WriteLine(“把y替换为:
  {0}”, chartester.Curr_Char);
  Console.Read();
  }
  static void Change_X(Object source,
   CharEventArgs e)
  { if (e.CurrChar==‘x’||e.CurrChar==‘X’)
  { Console.Write(“触发的字符是x ,”);
  e.CurrChar = ‘?’;
  }
  else
   Console.Write(“触发的字符不是 x , ”);
   }
  static void Change_Y(Object source,
   CharEventArgs e)
   { if(e.CurrChar==‘y’|| e.CurrChar== ‘Y’)
  { Console.WriteLine(“触发的字符是 y ”);
   e.CurrChar = ‘#’;
  }
   else
  Console.WriteLine(“触发字符不是 y ”);
   }
  }
  }
  上述程序的执行结果为:
  
  5 结束语
  
  其实,C#系统将事件视作一个代理类,并根据系统提供的各种状态自动实现跟踪和处理。当对象的某个状态发生了变化,代理就会自动调用,并执行代理的方法。事件和代理一样也支持多播,一个事件发送者可以同时触发多个处理事件的方法。
  
  参考文献
  [1]刘瑞新主编. C#网络编程及应用[M]. 北京: 机械工业出版社, 2005.
  [2]谢桂华, 魏亮等.Visual C#高级编程范例[M]. 北京: 清华大学出版社, 2004.
  [3]邵鹏鸣编著. Visual C#程序设计基础教程[M]. 北京: 清华大学出版社, 2005.
  [4]唐大仕编著. C#程序设计教程[M]. 北京: 清华大学出版社, 2003.

相关热词搜索:探讨 编程 事件 事件及其编程方法探讨 事件驱动编程 事件驱动编程 python

版权所有 蒲公英文摘 www.zhaoqt.net