C#委托、事件剖析(下)

摘要:
本节总结了事件。一方面,事件需要一个委托来创建约束。此约束指定事件源向事件订阅者发送的要求。事件订阅者的事件处理程序必须对应于此约束才能订阅事件。另一方面,事件订阅者在接收到事件后生成一个事件处理程序,而这个事件处理程序只能通过委托来完成。

本节对事件进行总结。

二、事件:

1、概念:Event:A member that enables an object or class to provide notifications;官方的解释是这样,就是说在C#中,事件是使

对象或者类具备通知能力的成员。比如说手机收到短信提醒我去开会,那么手机就充当了一个具备通知能力的成员。说白了,事件

的作用就是对象和类之间的信息传递的桥梁。

2、原理:源于发生-响应模型:

事件源(event source) + 事件本身(event) => 事件的订阅者(event subscriber) + 事件处理器(event handler)           

(另外还有事件的订阅者和事件源之间的订阅关系subscribe relationship)

还是以手机收到短信提醒我去开会为例,事件源:手机吗,事件:收到短信,事件的订阅者:我,事件处理器:去开会,订阅关系:我订阅手机

3、事件的声明:分为详细声明和简略声明:

(1)详细声明:

public delegate void MyDelegateEventHandler();
    public class Event
    {
        private MyDelegateEventHandler myDelegateEventHandler;
        public event MyDelegateEventHandler MyDelegate
        {
            add
            {
                this.myDelegateEventHandler += value;
            }
            remove
            {
                this.myDelegateEventHandler -= value;
            }
        }
    }

(2)简略说明:

public delegate void MyDelegateEventHandler();
    public class Event
    {
         public event MyDelegateEventHandler myDelegate;
    }

可以看到,在完整声明中首先添加了一个委托类型的字段,然后暴漏了添加和移除事件处理器的功能,但是我们经常用的是简略声明,因为代码更加简洁,

可以看出事件对外界隐藏了大部分功能,它的本质就是对其中委托字段的一个封装(encapsulation),防止外界偷用滥用委托字段。

那么问题来了:第一个问题:有了委托为什么还会有事件呢,事件内部不就是委托吗,原因是为了防止public型的委托字段在外面被滥用,比如委托可以用invoke调用,

但是事件只能在+=或-=的左侧,这样就增加了整个程序的安全性。

第二个问题:那委托和事件的关系什么样的呢?我们说事件是基于委托的。一方面,事件需要委托来做一个约束,这个约束规定了事件源发送什么要求给事件的订阅者,

事件订阅者的事件处理器必须和这个约束相对应才可以订阅这个事件,另一方面,事件订阅者收到事件以后做出事件处理器,而这个事件处理器必须通过委托才可以做到。

4、简单实例:

Example:做一个窗口,有文本框和按钮,点击按钮文本框显示时间,不用WindowsForms

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleApp14
{
    class Program
    {
        public static TextBox textBox;
        public static Button button;
        static void Main(string[] args)
        {
            Form form = new Form();
            TextBox textBox = new TextBox();
            Button button = new Button();
            form.Controls.Add(textBox);
            form.Controls.Add(button);
            textBox.Width = 400;
            button.Top = 100;
            button.Click += Button_Click;
            form.ShowDialog();
        }

        private static void Button_Click(object sender, EventArgs e)
        {
            textBox.Text = DateTime.Now.ToString();
        }
    }
}

C#委托、事件剖析(下)第1张

这里举的事例就是windowsforms内部的代码,我们说事件本身是不会发生的是由事件源内部的逻辑所触发,在本例中,并不是人按了按钮然后按钮触发了事件,

这其中还有一个小过程,就是当按钮被key down再key up时,向程序内部发送了一系列电讯号,通知电脑,然后再发生事件,

5、声明事件的相关约定:

用于声明事件的委托一般用:事件+EvnetHandler,参数一般有2个,第一个事件源,第二个EventArgs的派生类,用于触发事件的方法名一般为On+方法名,

访问级别Protected。可能有点蒙,举个实例就懂了。

Example:举一个顾客在KFC点餐的例子

namespace ConsoleApp15
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Waitor waitor = new Waitor();
            customer.Order += waitor.Serve;
            customer.Eat();
            customer.Pay();
        }
    }
    public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);
    public class Customer
    {
        public int Money { get; set; }
        public event OrderEventHandler Order;
        public void Pay()
        {
            Console.WriteLine($"OK,{Money} dollars");
        }
        public void Eat()
        {
            Console.WriteLine("Let's go to the KFC...");
            Console.WriteLine("Stand in front of the waitor...");
            Console.WriteLine("A hamburger,Please...");
            OnOrder();
        }
        protected void OnOrder()
        {
            OrderEventArgs orderEventArgs = new OrderEventArgs();
            orderEventArgs.Snack = "Hamburger";
            orderEventArgs.Size = "large";
            this.Order.Invoke(this, orderEventArgs);

        }
    }
    public class OrderEventArgs : EventArgs
    {
        public string Snack { get; set; }
        public string Size { get; set; }
    }
    class Waitor
    {
        public void Serve(Customer customer, OrderEventArgs e)
        {
            Console.WriteLine($"Here is your snack {e.Snack}");
            int price = 20;
            switch (e.Size)
            {
                case "large":
                    price *= 2;
                    break;
                case "small":
                    price *= 1;
                    break;
                default:
                    break;
            }
            customer.Money += price;
        }
    }
}

C#委托、事件剖析(下)第2张

按照事件的五个要素,首先需要事件源,做一个Customer类,还需要一个事件订阅者,做一个Waitor类,然后根据订阅关系去写具体的方法,订阅关系customer.Order += waitor.Serve; Customer点餐Waitor服务,waitor类中上餐并算好价格,这个时候需要一个事件处理器OrderEventHandler,这个委托的参数需要一个OrderEventArgs,创建这个类写好属性,在写好委托和事件,然后在Customer类中写点餐事件,点餐事件为Protected的,和public型的委托字段一样防止被外界滥用,提高安全性。

想融会贯通其实也不难,只需要将事件的5个要素每一个列举出来,那么最后事件也就出来了。

 

至此事件总结完毕,有不明之处还请指教。                2018-08-17   16:43:19

免责声明:文章转载自《C#委托、事件剖析(下)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇全基因组关联分析(Genome-Wide Association Study,GWAS)流程idea 设置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

正负无穷float('inf')的一些用法

示例:输入:[-2,1,-3,4,-1,2,1,-5,4],输出:6解释:连续子数组[4],-1,2,1]的和最大,为6。...

mini.DataGrid使用说明

√√√ ajaxOptionsObjectajax配置对象。√√√ idFieldString是行数据的唯一字段。设置为“client”之后,客户端将排序√√√√ totalCountNumber记录总数√√√ defaultColumnWidthNumber默认列宽100√√√√ showColumnsBoolean显示标头true√√√√ showPag...

Json 的日期格式转化(时区标准化)

在JavaScript中,这无疑可以通过初始化Data()对象//converttomsecsinceJan11970localTime=d轻松完成。获取时间();步骤2:接下来,通过Data()对象的getTimezoneOffset()方法//obtainlocalUTCoffsetandconverttomseclocalOffset=d找出本地时间偏...

如何在jenkins上新建一个项目及其简单配置

单击[新建]进入选择页面,您可以在此页面上配置项目(包括拉取源代码、修改连续构建时间以及在打包和部署之前修改配置文件)3。在General中,您可以设置要构建的版本,如下图5所示。在源代码管理模块中,您可以设置源代码地址(我们公司常用的Git)6。如果是自动构建,您可以将自动构建时间(即构建频率)设置为7。以下是构建中的一些设置。您可以使用shell修改源代...

LaTex学习笔记(1)——LaTeX文档插入图片的几种常用方法

2,插入bmp图片还没有找到直接插入bmp图片的方法。用gimp或fastoneimageviewer,将jpg质量选为最高,转换之后得到的图片质量较好。3,同时插入jpg和eps图片插入的命令不变。编译时使用Latex,dvi2pdf,两种格式的图片都可以显示。...

解决微信公众平台接口配置信息配置失败问题

填写完URL和TOKEN后,当您单击“提交”时,系统将始终提示您“配置失败”或其他错误,以确认URL所指向的后台页面代码是否正常。请确认TOKEN配置是否正常。此时,请检查INDEX页面的编码格式,并将其更改为GB2312进行尝试,这可能会解决您的问题。我想把这篇文章献给我浮躁的自己。...