委托和事件

来源:互联网 发布:网络摄像头端口 编辑:程序博客网 时间: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# 编程指南)

事件具有以下特点:

  • 发行者确定何时引发事件,订户确定执行何种操作来响应该事件。

  • 一个事件可以有多个订户。 一个订户可处理来自多个发行者的多个事件。

  • 没有订户的事件永远也不会引发。

  • 事件通常用于通知用户操作,例如,图形用户界面中的按钮单击或菜单选择操作。

  • 如果一个事件有多个订户,当引发该事件时,会同步调用多个事件处理程序。 要异步调用事件,请参见使用异步方式调用同步方法

  • 可以利用事件同步线程。

  • 在 .NET Framework 类库中,事件是基于 EventHandler 委托和 EventArgs 基类的。

3引发事件

如果希望您的类引发一个事件,您需要提供以下三个元素:

  • 提供事件数据的类。

  • 事件委托。

  • 引发事件的类。

    定义提供事件数据的类
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){
if (AlarmEvent!= null)
AlarmEvent(this, e);}
下面的示例定义名为 Set 的方法,该方法包含通过调用 OnAlarmEvent 方法来引发事件的逻辑。
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();        }    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大母脚趾头疼是怎么办 小脚趾内侧长茧怎么办 小脚趾肿了很痛怎么办 穿袜子大脚趾痛怎么办 脚指头长水泡很痒怎么办 走路脚打起泡了怎么办 剪完脚趾甲肿了怎么办 大脚趾关节处疼怎么办 战士10穿不进去怎么办 脚上皮肤干燥起皮怎么办 脚趾头冻了很痒怎么办 大脚趾里面有脓怎么办 大脚趾肉肿了怎么办 大脚趾边上肿了怎么办 大母脚趾关节疼怎么办 大脚趾有点歪了怎么办 大脚趾扭伤肿了怎么办 大脚趾外翻怎么办 知乎 颈椎带着胳膊疼怎么办 胳膊酸困无力是怎么办 腰疼引起的腿麻怎么办 手臂到手指麻痛怎么办 拔完智齿特别疼怎么办 躺着胃烧的难受怎么办 喝酒胃烧的难受怎么办 舌头破了特别疼怎么办 舌头又厚又大怎么办 牙齿咬到舌头了怎么办 舌头起了好多泡怎么办 舌头尖起泡很痛怎么办 舌头上起泡怎么办很疼 月经来了二十多天还不干净怎么办 三岁宝宝缺锌怎么办 无舌苔,舌头很红怎么办 嘴唇上肿了一块怎么办 下嘴唇突然肿了怎么办 上嘴唇突然肿厚怎么办 舌尖上火了好疼怎么办 舌头针扎似的疼怎么办 手麻了怎么办小妙招 月子生气奶少了怎么办