zoukankan      html  css  js  c++  java
  • 委托和事件

    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();
            }
        }
    }
    
  • 相关阅读:
    Vue--运行项目发送http://localhost:8080/sockjs-node/info请求报错,造成浏览器不能热更新
    Vue笔记--同局域网下访问本地项目
    Vue笔记--通过自定义指令实现按钮操作权限
    css/css3实现未知宽高元素的垂直居中和水平居中
    【转载】Vue路由history模式踩坑记录:nginx配置解决404问题
    给动态生成的input框,添加readonly属性
    layui-form下隐藏元素的验证问题
    layui的省市县三级联动
    webstorm-激活码
    采坑
  • 原文地址:https://www.cnblogs.com/yellowsail/p/1951339.html
Copyright © 2011-2022 走看看