c#事件详解

什么是事件

image.png

  • 事件是类的成员
  • 统一:

image.png

image.png

  • 设计模式:事件模式

事件的应用

image.png

事件不会主动发生,由拥有者的内部的某个逻辑触发,才会发生通知

点击事件:是靠点击时是鼠标向硬件发送的电信号,windows还会记录按钮被按下的状态,松开时被绘制成松开的状态,而且被记录。如果有其他对象订阅了点击事件,这些事件的响应者就可以开始工作了。即,我们的程序在事件的驱动下开始运行了。

例案

image.png

这里的0319AF78.png就是事件成员

案例1:认识订阅事件

using System;
using System.Collections.Generic;
using System.Timers;
//using System.Windows.Forms;
namespace NamespaceEncasement

{

    class Program
    {
        static void Main(string[] args)
        {
            Timer timer = new Timer();//timer就是事件的拥有者
            timer.Interval = 1000;
            Boy boy = new Boy();//boy是事件的响应者
            timer.Elapsed += boy.Action;//+=是订阅事件,左边Elapsed是事件,右边要跟上事件响应者的事件处理器
            timer.Start();
            Console.ReadLine();

        }

        class Boy//事件处理器
        {
            internal void Action(object sender, ElapsedEventArgs e)
            {
                Console.WriteLine("Jump!");
            }
        }
    }
}

事件组合二

image.png

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
namespace NamespaceEncasement

{

    class Program
    {
        static void Main(string[] args)
        {
            Form form = new Form();//事件的拥有者
            Controller controller = new Controller(form);//事件的响应者
            form.ShowDialog();

        }
        static bool Test(List<int>intList)

        {
            foreach (var item in intList)
            {
                if (item<=10)
                {
                    return false;
                }
            }
            return true;
        }
        class Controller
        {
            private Form form;
            public Controller(Form form)
            {
                if (form!=null)
                {
                    this.form = form;//左边实例字段,右边是参数
                    this.form.Click += this.FormClicked;//+=左边订阅事件,右边是事件处理器,具体见方法,整个语句是事件订阅者
               //「this」 就是Controller这个类的实例
 }
            }

            private void FormClicked(object sender, EventArgs e)
            {
              this.form.Text=DateTime.Now.ToString();
            }
        }

    }

    }



事件组合三

image.png

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
namespace NamespaceEncasement

{

    class Program
    {
        static void Main(string[] args)
        {
            MyForm myform = new MyForm();//事件的拥有者
            myform.Click += myform.FormClicked;
            //Click是事件
            myform.ShowDialog();
         

        }

  

        class MyForm:Form
        {
        

            internal void FormClicked(object sender, EventArgs e)
            {
                this.Text = DateTime.Now.ToString();
            }
        }

    }

    }



应用广泛

image.png

  • 事件拥有者是事件响应者的一个字段成员

  • 事件响应者用方法订阅着成员的某个事件

    image.png

image.png

image.png

image.png

image.png

第三种挂接方式:委托匿名方法

image.png

lamda挂接

image.png

事件的声明

image.png

事件是基于委托的

  • 事件需要一个委托事件来作为约束,这个约束既规定了事件能够发送什么消息事件的响应者,也规定了事件的响应者能收到什么样的事件消息,这也就规定了事件响应者的事件处理器必须跟这个约束匹配上
  • 当事件的响应者为事件的拥有者提供了能够匹配这个事件的事件处理器之后,需要一个地方保存和记录事件处理,这个地方就是委托的实例

准备一个委托,这个委托既能够事件相应的处理器必须跟时间匹配上才能完成订阅

事件委托的关系

image.png

原始声明

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace NamespaceEncasement

{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Waiter waiter = new Waiter();
            customer.Order += waiter.Action;
            customer.Action();
            customer.PayTheBill();
        }


    }
    public class OrderEventArgs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }
    public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs

    public class Customer//事件拥有者
    {
        private OrderEventHandler orderEventHandler;//用于存储或者引用事件处理器的 
        public double Bill { get; set; }
        public event OrderEventHandler Order//声明事件
        {
            add
            {
                this.orderEventHandler += value;//事件添加器
            }
            remove
            {
                this.orderEventHandler -= value;//事件移出器
            }
        }
        public void PayTheBill()
        {
            Console.WriteLine("I will pay ${0}", this.Bill);
        }
        //声明点菜事件
        public void Walkin()
        {
            Console.WriteLine("Walk into the restaurant");

        }
        public void SitDown()
        {
            Console.WriteLine("Sit down.");

        }
        public void Think()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Let me think...");
                Thread.Sleep(1000);
            }
            if (this.orderEventHandler != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = "Kongpao CHichen";
                e.Size = "large";
                this.orderEventHandler.Invoke(this, e);

            }

        }
        public void Action()
        {
            Console.ReadLine();
            this.Walkin();
            this.SitDown();
            this.Think();

        }



    }
    public class Waiter
    {
        internal void Action(Customer customer, OrderEventArgs e)
        {
            Console.WriteLine("I will serve you the dish-{0}", e.DishName);
            double price = 10;
            switch (e.Size)
            {
                case "small":
                    price = price * 05;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }
            customer.Bill = +price;
        }
    }
}

打印结果为


Walk into the restaurant
Sit down.
Let me think...
Let me think...
Let me think...
Let me think...
Let me think...
I will serve you the dish-Kongpao CHichen
I will pay $15
请按任意键继续. .

想5秒以后就出发了order事件,而waiter用action订阅了事件,那就开始执行了

简略格式声明

 private OrderEventHandler orderEventHandler;
public event OrderEventHandler Order//声明事件
        {
            add
            {
                this.orderEventHandler += value;//事件添加器
            }
            remove
            {
                this.orderEventHandler -= value;//事件移出器
            }
        }

把37行的代码改为public event OrderEventHandler Order;

   if (this.Order != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = "Kongpao CHichen";
                e.Size = "large";
                this.Order.Invoke(this, e);

            }

跟着改变

完整简略声明代码

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace NamespaceEncasement

{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Waiter waiter = new Waiter();
            customer.Order += waiter.Action;
            customer.Action();
            customer.PayTheBill();
        }


    }
    public class OrderEventArgs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }
    public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs

    public class Customer//事件拥有者
    {
        //用于存储或者引用事件处理器的 

        public double Bill { get; set; }
        public event OrderEventHandler Order;//声明事件
     
        public void PayTheBill()
        {
            Console.WriteLine("I will pay ${0}", this.Bill);
        }
        //声明点菜事件
        public void Walkin()
        {
            Console.WriteLine("Walk into the restaurant");

        }
        public void SitDown()
        {
            Console.WriteLine("Sit down.");

        }
        public void Think()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Let me think...");
                Thread.Sleep(1000);
            }
            if (this.Order != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = "Kongpao CHichen";
                e.Size = "large";
                this.Order.Invoke(this, e);

            }

        }
        public void Action()
        {
            Console.ReadLine();
            this.Walkin();
            this.SitDown();
            this.Think();

        }



    }
    public class Waiter
    {
        internal void Action(Customer customer, OrderEventArgs e)
        {
            Console.WriteLine("I will serve you the dish-{0}", e.DishName);
            double price = 10;
            switch (e.Size)
            {
                case "small":
                    price = price * 05;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }
            customer.Bill = +price;
        }
    }
}



为什么要有事件

image.png

如果把委托的事件,改为字段。

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace NamespaceEncasement

{
    class Program
    {
        static void Main(string[] args)
        {
            Console.ReadLine();
            Customer customer = new Customer();
            Waiter waiter = new Waiter();
            customer.Order += waiter.Action;//这个时候,Order已经变成了字段
            //customer.Action();
            //customer.PayTheBill();
            OrderEventArgs e = new OrderEventArgs();
            e.DishName = "M";
            e.Size = "large";
            OrderEventArgs e2 = new OrderEventArgs();
            e2.DishName = "B";
            e2.Size = "large";
            Customer badGuy = new Customer();
            badGuy.Order += waiter.Action;
         
            badGuy.Order.Invoke(customer,e);
           badGuy.Order.Invoke(customer, e2);
            customer.PayTheBill();
        }


    }
    public class OrderEventArgs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }
    public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs

    public class Customer//事件拥有者
    {
        //用于存储或者引用事件处理器的 

        public double Bill { get; set; }
        public OrderEventHandler Order;
     
        public void PayTheBill()
        {
            Console.WriteLine("I will pay ${0}", this.Bill);
        }
        //声明点菜事件
        public void Walkin()
        {
            Console.WriteLine("Walk into the restaurant");

        }
        public void SitDown()
        {
            Console.WriteLine("Sit down.");

        }
        public void Think()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Let me think...");
                Thread.Sleep(1000);
            }
            if (this.Order != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = "Kongpao CHichen";
                e.Size = "large";
                this.Order.Invoke(this, e);

            }

        }
        public void Action()
        {
            Console.ReadLine();
            this.Walkin();
            this.SitDown();
            this.Think();

        }



    }
    public class Waiter
    {
        internal void Action(Customer customer, OrderEventArgs e)
        {
            Console.WriteLine("I will serve you the dish-{0}", e.DishName);
            double price = 10;
            switch (e.Size)
            {
                case "small":
                    price = price * 05;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }
            customer.Bill +=price;
        }
    }
}



跟指针很像,会变得很乱

可以不单独声明委托

public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs 这句可以不要

public delegate void OrderEventHandler(Customer customer, OrderEventArgs e)
public event OrderEventHandler Order;

改为

改为public EventHandler Order;

EventHandler 的定义

namespace System
{
    //
    // 摘要:
    //     表示将用于处理不具有事件数据的事件的方法。
    //
    // 参数:
    //   sender:
    //     事件源。
    //
    //   e:
    //     不包含事件数据的对象。
    [ComVisible(true)]
    public delegate void EventHandler(object sender, EventArgs e);
}

因此要把事件响应者类型进行修改

public class Waiter
    {
        internal void Action(Object sender, EventArgs e)
        {
            Customer customer = sender as Customer;//转换sender
            OrderEventArgs orderInfor = e as OrderEventArgs;// 转换e
            Console.WriteLine("I will serve you the dish-{0}", orderInfor.DishName);//e改为orderInfor
            double price = 10;
            switch (orderInfor.Size)//e改为orderInfor
            {
                case "small":
                    price = price * 05;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }
            customer.Bill +=price;
        }
    }
}

一个方法只做一件事

image.png

因此要对Think进行改造

 public void Think()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Let me think...");
                Thread.Sleep(1000);
            }
            this.OnOrder("m","large");

        }
        protected void OnOrder(string disName,string size)
        {
            if (this.Order != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = disName;
                e.Size = size;
                this.Order.Invoke(this, e);//事件的触发者用this代替了

            }
        }

完整代码

using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace NamespaceEncasement

{
    class Program
    {
        static void Main(string[] args)
        {
        
            Customer customer = new Customer();
            Waiter waiter = new Waiter();
            customer.Order += waiter.Action;//这个时候,Order已经变成了字段
            customer.Action();
            customer.PayTheBill();
 
        }


    }
    public class OrderEventArgs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }
    //public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs

    public class Customer//事件拥有者
    {
        //用于存储或者引用事件处理器的 

        public double Bill { get; set; }
        public EventHandler Order;
   
        public void PayTheBill()
        {
            Console.WriteLine("I will pay ${0}", this.Bill);
        }
        //声明点菜事件
        public void Walkin()
        {
            Console.WriteLine("Walk into the restaurant");

        }
        public void SitDown()
        {
            Console.WriteLine("Sit down.");

        }
        public void Think()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Let me think...");
                Thread.Sleep(1000);
            }
            this.OnOrder("m","large");

        }
        protected void OnOrder(string disName,string size)
        {
            if (this.Order != null)

            {
                OrderEventArgs e = new OrderEventArgs();
                e.DishName = disName;
                e.Size = size;
                this.Order.Invoke(this, e);//事件的触发者用this代替了

            }
        }
        public void Action()
        {
            Console.ReadLine();
            this.Walkin();
            this.SitDown();
            this.Think();

        }



    }
    public class Waiter
    {
        internal void Action(Object sender, EventArgs e)
        {
            Customer customer = sender as Customer;//转换sender
            OrderEventArgs orderInfor = e as OrderEventArgs;// 转换e
            Console.WriteLine("I will serve you the dish-{0}", orderInfor.DishName);//e改为orderInfor
            double price = 10;
            switch (orderInfor.Size)//e改为orderInfor
            {
                case "small":
                    price = price * 05;
                    break;
                case "large":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }
            customer.Bill +=price;
        }
    }
}

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值