• 事件Event


    1.什么是事件,使对象或者类具有通知功能的成员。//为了解决字段在外部被滥用,推出了事件

    事件的功能能=通知+可选的事件参数(具体的详细信息,包括谁发送了消息,发送的什么消息)

    使用:用于对象或者类件的动作协调与信息传递(消息推送)

    事件模型(发生,响应模型),事件是工具,不会主动通知别人,被事件的拥有者的内部逻辑触发。

    2.事件模型中的5个部分:

    • 事件的拥有者:对象
    • 事件的成员:event成员
    • 事件的响应者:对象
    • 事件处理器:本质上是一个回调方法(方法成员)
    • 事件订阅:把事件处理器与事件关联在一起,本质上事一种委托类型为基础的“约定”

    注意:事件不是委托类型的字段,因为如果是的话,就会不安全。不安全表现在,如果事件真的成为了委托类型的字段,那么,字段既可以存在于+=运算符的左边,还可以存在于.操作符的左侧,这时就能调用Invoke(其他实例,事件消息)方法来触发事件,触发事件的方法一定不能被外部访问到。

    • 一个事件可以挂接多个事件处理器
    • 一个事件处理器可以被多个事件挂接
      class Program
        {
            static void Main(string[] args)
            {
                Customer customer = new Customer();//事件的拥有者
                Waiter waiter=new Waiter();//响应者,服务员响应顾客的点餐
                customer.Order += waiter.Action;//事件处理器Waiter.Action,+=是事件的订阅。为类的事件成员挂接事件处理器,或者挂接(一个委托类型的实例:如new EventHnadler(waiter,Action))
              
    //这样看起来像是委托类型的实例去添加方法的引用一样,这样更像是order是委托类型的实例,顾客的订单事件挂接服务员的处理方法 customer.Action();//事件的触发必须由事件的拥有者来做
    customer.PayTheBill(); Console.ReadLine(); } } public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//void是事件处理器也就是方法的返回值类型,EventHandler后缀存在的意义 1.立刻知道这个委托是用来声明事件的 2.表明是用来约束事件处理器的 3.这个委托将来创建的实例是为了存储事件处理器的 public class OrderEventArgs : EventArgs//传递事件信息的类EventArgs { public string DishName { get; set; } public string Size { get; set; } } public class Customer { public double Bill { get; set; } public void PayTheBill() { Console.WriteLine("I will pay{0}",this.Bill); } //事件需要委托来约束,规定了事件能发送什么样的消息给事件接收者,规定了事件接受者能收到什么样的消息,事件接受者的事件处理器必须能和事件匹配 //当事件的响应者向事件的拥有者提供了能够匹配这个事件的事件处理器后,保存事件处理器,引用事件处理器就必须用委托 //private OrderEventHandler orderEventHandler;//这个委托字段是用来存储,引用个事件处理的 //public event OrderEventHandler Order //用上面那个委托类型来约束事件,声明事件 //{ // add { this.orderEventHandler += value; }//事件处理器的添加器,value是外界传进来eventhandler // remove { this.orderEventHandler -= value; } //}//声明事件的代码 public event OrderEventHandler Order;//声明了一个事件,能够让对象之间的关系更加有道理,看起来像是在声明一个字段,重点是Event 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("宫保鸡丁", "large"); } protected void OnOrder(string dishName,string size)//事出有因,因为调用了OnOrder这个方法,所以Order这个事件触发了,并且public这个方法不能被外界触发 { if (this.Order != null)//餐馆很忙,没有事件处理器也就是waiter来响应你的事件 { OrderEventArgs e = new OrderEventArgs();//事件消息,保存点的什么菜,多大的分量 e.DishName = dishName; e.Size = size; this.Order.Invoke(this, e);//此处传入的参数是在委托中定义好的,触发事件的动作,传入是谁点的餐,点的什么餐 } } public void Action() { Console.ReadLine(); this.Walkin(); this.SitDown(); this.Think(); } } public class Waiter { public void Action(Customer customer, OrderEventArgs e)//第一个参数这个事件的拥有者是Customer触发的,第二个参数是EventArgs的派生类,这个事件里面是什么内容,关于事件的数据 { Customer customer1 = customer as Customer; OrderEventArgs order = e as OrderEventArgs; Console.WriteLine("I will server you the dish-{0}", e.DishName); double price = 10; switch (e.Size) { case "small": price=price *0.5; break; case "large": price=price*1.5; break; default: break; } customer.Bill += price; } }

    为什么要使用委托类型来声明事件?为什么事件是基于委托的?

    • 对于Source来说,是为了表明Source能够对外界传递哪些消息
    • 对于订阅者来说,他是一种约定,约定了能够使用什么样的签名方法方法来处理,也就是事件处理函数的
    • 委托类型的实例用于存储(引用)事件处理器,

    对比事件与属性

    • 属性不是字段----------属性是字段的包装器,保护字段
    • 事件不是委托字段----------他是委托字段的包装器,保护委托字段不被外界随便调用
  • 相关阅读:
    一生不可错过的五句话
    分布式缓存系统Memcached简介与实践[转]
    telnet serverip serverport 可以测试服务器端口是否通
    使用c#生成高品质小空间的缩略图
    sql server2005对tsql的增强之在聚合函数的后面使用over关键字
    (转)让你受益终身的10个Word实用技巧
    sql取所有记录中每天的最后一笔交易的记录
    屏蔽服务器端包含在文件不存在时报错的错误信息
    c#农历日历类
    Niubility 英语教程
  • 原文地址:https://www.cnblogs.com/1521681359qqcom/p/11222476.html
Copyright © 2020-2023  润新知