zoukankan      html  css  js  c++  java
  • Event

        • 1.发布者和订阅者
        • 2.声明事件
        • 3.订阅事件
        • 4.触发事件
        • 5.标准事件用法
          • 5.1 通过扩展EventArgs来传递数据
          • 5.2 移除事件处理程序
        • 6.事件访问器

    1.发布者和订阅者

    • 发布者(publisher) 发布某个事件的类或结构,其他类可以在该事件发生时得到通知
    • 订阅者(subscriber) 注册并在事件发生时得到通知的类或结构。
    • 事件处理程序(event handler) 由订阅者注册到事件的方法,在发布者触发事件后执行。
    • 触发(raise)事件 调用(invoke)或触发(fire)事件的术语,当事件触发时,所有注册到它的方法依次调用。 事件包含了一个私有的委托。
      image

    2.声明事件

    • 事件声明在一个类中
    • 事件需要委托类型的名称,任何附加到事件(如注册)的处理程序都必须与委托类型的签名和返回类型匹配
    • 事件声明为public,这样其他类或结构才可以在上面注册
    • 不能使用new表达式创建事件对象
    class Incrementer
    {
        public event EventHandler publish; 
    }
    

    可以使用逗号分隔多个事件声明,

    public event EventHandler MyEvent1, MyEvent1, MyEvent1;
    

    还可以使用static关键字让事件变成静态的,

    public static event EventHandler MyEvent;
    

    事件是类或结构的成员,所以有以下几条特性:

    • 不能在一段可执行代码中声明事件
    • 必须声明在类或结构中
    • 事件成员隐式自动初始化为null

    3.订阅事件

    使用+=运算符来为事件增加事件处理程序

    Incrementer i = new Incrementer();
    Incrementer.EventHandler += i.Method1; //方法引用形式
    Incrementer.EventHandler += StaticClass.Method2; //方法引用形式
    i.EventHandler += new MyDel(i2.Method3); // 委托形式
    Incrementer.EventHandler += () => count++; // Lambda表达式
    Incrementer.EventHandler += delegate { count++ }; // 匿名方法
    

    4.触发事件

    • 在触发事件前与null进行比较,查看是否包含事件处理程序
    if(EventHandler != null)
    {
        Eventhandler(param1, param2);
    }
    

    将事件声明和触发事件的代码放在一起就有了发布者类的声明。

    delegate void Handler();
    class Incrementer
    {
        public event Handler CountedADozen;
        public void DoCount()
        {
            for(int i = 1;i < 100;i++)
            {
                if(i % 12 == 0 && CountedADozen != null)
                {
                    CountedADozen();
                }
            }
        }
    }
    class Dozens
    {
        public int DozensCount { get; set; }
        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;
        }
        void IncrementDozensCount()
        {
            DozensCount++;
        }
    }
    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozens = new Dozens(incrementer);
            incrementer.DoCount();
            Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
            Console.ReadKey();
        }
    }
    

    output

    Number of dozens = 8
    

    5.标准事件用法

    delegate void EventHandler(object sender, EventArgs e); //使用系统定义的Eventhandler委托
    class Incrementer
    {
        public event EventHandler CountedADozen;
        public void DoCount()
        {
            for(int i = 1;i < 100;i++)
            {
                if(i % 12 == 0 && CountedADozen != null)
                {
                    CountedADozen(this, null); // 触发事件时使用EventHandler的参数
                }
            }
        }
    }
    class Dozens
    {
        public int DozensCount { get; set; }
        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount; // 添加事件处理程序
        }
        void IncrementDozensCount(object source, EventArgs e) // 事件处理程序的签名必须与委托的签名匹配
        {
            DozensCount++;
        }
    }
    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozens = new Dozens(incrementer);
            incrementer.DoCount();
            Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
            Console.ReadKey();
        }
    }
    

    5.1 通过扩展EventArgs来传递数据

    为了向事件处理程序的第二个参数传入数据,需要声明一个派生自EventArgs的自定义类。

    public class IncrementerEventArgs : EventArgs
    {
        public int IterationCount { get; set; }
    }
    

    之后使用泛型委托EventHandler<>,

    public event EventHandler<IncrementerEventArgs> CountedADozen;
    
    public class IncrementerEventArgs : EventArgs
    {
        public int IterationCount { get; set; }
    }
    delegate void EventHandler<T>(object sender, T e);
    class Incrementer
    {
        public event EventHandler<IncrementerEventArgs> CountedADozen;
        public void DoCount()
        {
            IncrementerEventArgs args = new IncrementerEventArgs();
            for (int i = 1;i < 100;i++)
            {
                if(i % 12 == 0 && CountedADozen != null)
                {
                    args.IterationCount = i;
                    CountedADozen(this, args);
                }
            }
        }
    }
    class Dozens
    {
        public int DozensCount { get; set; }
        public Dozens(Incrementer incrementer)
        {
            DozensCount = 0;
            incrementer.CountedADozen += IncrementDozensCount;
        }
        void IncrementDozensCount(object source, IncrementerEventArgs e)
        {
            Console.WriteLine($"Incremented at iteration: {e.IterationCount} in {source.ToString()}");
            DozensCount++;
        }
    }
    class Program
    {
        static void Main()
        {
            Incrementer incrementer = new Incrementer();
            Dozens dozens = new Dozens(incrementer);
            incrementer.DoCount();
            Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
            Console.ReadKey();
        }
    }
    

    output

    Incremented at iteration: 12 in Incrementer
    Incremented at iteration: 24 in Incrementer
    Incremented at iteration: 36 in Incrementer
    Incremented at iteration: 48 in Incrementer
    Incremented at iteration: 60 in Incrementer
    Incremented at iteration: 72 in Incrementer
    Incremented at iteration: 84 in Incrementer
    Incremented at iteration: 96 in Incrementer
    Number of dozens = 8
    

    5.2 移除事件处理程序

    class Publisher
    {
        public event EventHandler SimpleEvent;
        public void RaiseTheEvent() { SimpleEvent(this, null); }
    }
    class Subscriber
    {
        public void MethodA(object o, EventArgs e) { Console.WriteLine("AAA"); }
        public void MethodB(object o, EventArgs e) { Console.WriteLine("BBB"); }
    }
    class Program
    {
        static void Main()
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber();
            p.SimpleEvent += s.MethodA;
            p.SimpleEvent += s.MethodB;
            p.RaiseTheEvent();
            Console.WriteLine("Remove MethodB");
            p.SimpleEvent -= s.MethodB; // 移除事件处理程序
            p.RaiseTheEvent();
            Console.ReadKey();
        }
    }
    

    output

    AAA
    BBB
    Remove MethodB
    AAA
    

    6.事件访问器

    要改变两个运算符+=和-=的操作,可以为事件定义事件访问器。

        public event EventHandler CountedADozen
        {
            add {...}
            remove {...}
        }
    
    class Program
    {
        static void Main(string[] args)
        {
            Publishser p = new Publishser();
            p.NumberChanged -= Subscriber1.OnNumberChanged;
            p.NumberChanged += Subscriber2.OnNumberChanged;
            p.NumberChanged += Subscriber3.OnNumberChanged;
            p.DoSomething();
            Console.ReadKey();
        }
    }
    public delegate string GeneralEventHandler(); // 定义委托
    public class Publishser // 定义事件发布者
    {
        private GeneralEventHandler numberChanged; // 声明一个委托变量
        public event GeneralEventHandler NumberChanged // 定义事件访问器
        {
            add // 改变 += 运算符
            {
                numberChanged = value;
            }
            remove // 改变 -= 运算符
            {
                numberChanged = value;
            }
        }
        public void DoSomething()
        {
            if (numberChanged != null)
            {
                string rtn = numberChanged();
                Console.WriteLine(rtn);
            }
        }
    }
    public class Subscriber1 // 定义事件订阅者
    {
        public static string OnNumberChanged()
        {
            return "Subscriber1";
        }
    }
    public class Subscriber2
    {
        public static string OnNumberChanged()
        {
            return "Subscriber2";
        }
    }
    public class Subscriber3
    {
        public static string OnNumberChanged()
        {
            return "Subscriber3";
        }
    }
    

    output

    Subscriber3
  • 相关阅读:
    X
    W
    J
    A
    Q
    P
    B
    排列和组合的求解
    深度学习之序列处理
    32位和64位数据类型大小对比
  • 原文地址:https://www.cnblogs.com/jizhiqiliao/p/10649149.html
Copyright © 2011-2022 走看看