委托和事件
来源:互联网 发布:网络摄像头端口 编辑:程序博客网 时间:2024/06/05 02:28
http://www.cnblogs.com/yellowsail/archive/2011/02/11/1951339.html
1.委托
委托类型的声明与方法签名相似, 有一个返回值和任意数目任意类型的参数:
public delegate void TestDelegate(string message);public delegate int TestDelegate(MyType m, long num);
delegate 是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。
委托是事件的基础。
通过将委托与命名方法或匿名方法关联,可以实例化委托。 有关更多信息,请参见命名方法和匿名方法。
必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。 有关方法签名中允许的差异程度的更多信息,请参见委托中的变体(C# 和 Visual Basic)。 为了与匿名方法一起使用,委托和与之关联的代码必须一起声明
示例:
// Declare delegate -- defines required signature:delegate double MathAction(double num);class DelegateTest{ // Regular method that matches signature: static double Double(double input) { return input * 2; } static void Main() { // Instantiate delegate with named method: MathAction ma = Double; // Invoke delegate ma: double multByTwo = ma(4.5); Console.WriteLine(multByTwo); // Instantiate delegate with anonymous method: MathAction ma2 = delegate(double input) { return input * input; }; double square = ma2(5); Console.WriteLine(square); // Instantiate delegate with lambda expression MathAction ma3 = s => s * s * s; double cube = ma3(4.375); Console.WriteLine(cube); }}
2事件
类或对象可以通过事件向其他类或对象通知发生的相关事情。 发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。
在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件。 可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件。 IDE 会自动添加空事件处理程序方法和订阅事件的代码。 有关更多信息,请参见如何:订阅和取消订阅事件(C# 编程指南)。
事件具有以下特点:
3引发事件
发行者确定何时引发事件,订户确定执行何种操作来响应该事件。
一个事件可以有多个订户。 一个订户可处理来自多个发行者的多个事件。
没有订户的事件永远也不会引发。
事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。
如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。 要异步调用事件,请参见使用异步方式调用同步方法。
可以利用事件同步线程。
在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的。
如果希望您的类引发一个事件,您需要提供以下三个元素:
提供事件数据的类。
事件委托。
引发事件的类。
定义提供事件数据的类public class AlarmEventArgs : EventArgs{ private DateTime alarmTime; private bool snoozeOn = true; public AlarmEventArgs(DateTime time) { this.alarmTime = time; } public DateTime Time { get { return this.alarmTime; } } public bool Snooze { get { return this.snoozeOn; } set { this.snoozeOn = value; } } }定义事件的委托public delegate void AlarmEventHandler(object sender, AlarmEventArgs e);定义引发事件的类public event AlarmEventHandler AlarmEvent;定义事件实现后,您必须确定引发事件的时间。 通过在定义事件的类或派生类中调用受保护的 OnEventName 方法来引发事件。 随后,OnEventName方法引发事件。
受保护的 OnEventName方法也允许派生类重写事件,而不必向其附加委托。 派生类必须始终调用基类的 OnEventName方法以确保注册的委托接收到事件。
下面的示例定义负责引发 AlarmEvent 事件的 OnAlarmEvent 方法。
protected void OnAlarmEvent(AlarmEventArgs e){下面的示例定义名为 Set 的方法,该方法包含通过调用 OnAlarmEvent 方法来引发事件的逻辑。if (AlarmEvent!= null)AlarmEvent(this, e);}public void Set(){ while (true) { System.Threading.Thread.Sleep(2000); DateTime currentTime = DateTime.Now; // Test whether it is time for the alarm to go off. if (currentTime.Hour == alarmTime.Hour && currentTime.Minute == alarmTime.Minute) { AlarmEventArgs args = new AlarmEventArgs(currentTime); OnAlarmEvent(args); if (! args.Snooze) return; else this.alarmTime = this.alarmTime.AddMinutes(this.interval); } }}4完整示例其他资源
处理和引发事件如何:引发和使用事件如何:在类中实现事件using System;namespace EventSample{ // Class that contains the data for // the alarm event. Derives from System.EventArgs. // public class AlarmEventArgs : EventArgs { private bool snoozePressed; private int nrings; //Constructor. // public AlarmEventArgs(bool snoozePressed, int nrings) { this.snoozePressed = snoozePressed; this.nrings = nrings; } // The NumRings property returns the number of rings // that the alarm clock has sounded when the alarm event // is generated. // public int NumRings { get { return nrings;} } // The SnoozePressed property indicates whether the snooze // button is pressed on the alarm when the alarm event is generated. // public bool SnoozePressed { get {return snoozePressed;} } // The AlarmText property that contains the wake-up message. // public string AlarmText { get { if (snoozePressed) { return ("Wake Up!!! Snooze time is over."); } else { return ("Wake Up!"); } } } } // Delegate declaration. // public delegate void AlarmEventHandler(object sender, AlarmEventArgs e); // The Alarm class that raises the alarm event. // public class AlarmClock { private bool snoozePressed = false; private int nrings = 0; private bool stop = false; // The Stop property indicates whether the // alarm should be turned off. // public bool Stop { get {return stop;} set {stop = value;} } // The SnoozePressed property indicates whether the snooze // button is pressed on the alarm when the alarm event is generated. // public bool SnoozePressed { get {return snoozePressed;} set {snoozePressed = value;} } // The event member that is of type AlarmEventHandler. // public event AlarmEventHandler Alarm; // The protected OnAlarm method raises the event by invoking // the delegates. The sender is always this, the current instance // of the class. // protected virtual void OnAlarm(AlarmEventArgs e) { AlarmEventHandler handler = Alarm; if (handler != null) { // Invokes the delegates. handler(this, e); } } // This alarm clock does not have // a user interface. // To simulate the alarm mechanism it has a loop // that raises the alarm event at every iteration // with a time delay of 300 milliseconds, // if snooze is not pressed. If snooze is pressed, // the time delay is 1000 milliseconds. // public void Start() { for (;;) { nrings++; if (stop) { break; } else { if (snoozePressed) { System.Threading.Thread.Sleep(1000); } else { System.Threading.Thread.Sleep(300); } AlarmEventArgs e = new AlarmEventArgs(snoozePressed, nrings); OnAlarm(e); } } } } // The WakeMeUp class has a method AlarmRang that handles the // alarm event. // public class WakeMeUp { public void AlarmRang(object sender, AlarmEventArgs e) { Console.WriteLine(e.AlarmText +"/n"); if (!(e.SnoozePressed)) { if (e.NumRings % 10 == 0) { Console.WriteLine(" Let alarm ring? Enter Y"); Console.WriteLine(" Press Snooze? Enter N"); Console.WriteLine(" Stop Alarm? Enter Q"); String input = Console.ReadLine(); if (input.Equals("Y") ||input.Equals("y")) { return; } else if (input.Equals("N") || input.Equals("n")) { ((AlarmClock)sender).SnoozePressed = true; return; } else { ((AlarmClock)sender).Stop = true; return; } } } else { Console.WriteLine(" Let alarm ring? Enter Y"); Console.WriteLine(" Stop Alarm? Enter Q"); String input = Console.ReadLine(); if (input.Equals("Y") || input.Equals("y")) { return; } else { ((AlarmClock)sender).Stop = true; return; } } } } // The driver class that hooks up the event handling method of // WakeMeUp to the alarm event of an Alarm object using a delegate. // In a forms-based application, the driver class is the // form. // public class AlarmDriver { public static void Main(string[] args) { // Instantiates the event receiver. WakeMeUp w = new WakeMeUp(); // Instantiates the event source. AlarmClock clock = new AlarmClock(); // Wires the AlarmRang method to the Alarm event. clock.Alarm += new AlarmEventHandler(w.AlarmRang); clock.Start(); } }}
- c# 委托和委托事件
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- 事件和委托
- 委托和事件
- 事件和委托学习
- 关于委托和事件
- C# 委托和事件
- 委托和事件
- 委托和事件
- 事件和委托
- 委托和事件
- 委托和事件
- 委托和事件
- 委托和事件
- .Net在线编辑器:KindEditor及CkEditor配置说明
- 后台页面访问权限:页面基类&内置票据认证 使用方法
- 如何加入一个开源项目?
- 由Flex 3進入Flex 4的必備知識 PART 4 – Flash Builder的程式撰寫工具
- cxf 发布webservice报 You have more than one version of 'org.apache.commons.logging.Log' visible
- 委托和事件
- 关于客户端与数据库服务器端的时间同步问题
- 学习 JSON ( JavaScript Object Notation )
- 远程登录mysql服务器配置
- 由Flex 3進入Flex 4的必備知識 PART 5 – Flex 4的雙向Data Binding
- 用GDB调试--目录
- 用Visual C#创建Windows服务程序
- C# 可变数量参数的使用
- C#:params 关键字的学习