事件是不是委托类型的字段?是不是一个特殊类型的委托类型的字段?
简略声明格式“确实像”一个字段;事件并不是一个字段;
反编译器中查看:
<蓝色箭头:事件 菱形:字段)>
①属性(Bill)简略声明的时候,为我们准备的后台字段
②第二条:编译器,为我们简化的事件声明方式,准备了那个委托类型的字段。
其实我们委托类型的字段,虽然没有手动声明在脚本中,但其实它只是没有出现在我们的代码当中。实际上出现在了后台当中。为我们将来储存事件处理器的。
继续优化
事件平台当中,我们可以去使用一种非常通用的委托:EventHandler委托。
因为OrderEventArgs是EventArgs所派生出来的(是EventArgs的子类)。委托类型从OrderEventHandler变成EventArgs,势必约定已经打破了,改变了。对应的事件处理器也一定会发生改变。原本的事件处理器的参数列表,将不会符合要求。
①as
完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
//事件模型的 [五个组成部分]
//事件的拥有者【类】------>Customer类
//事件【event关键字修饰】------>OnOrder点餐事件
//事件的响应者【类】------>Waiter类
//事件处理器【方法 - 受到约束的方法】------>TakeAction方法
//事件的订阅关系【+=】------>+=
public delegate void OrderEventHandler(Customer _customer, OrderEventArg _e);
public class EventEx1 : MonoBehaviour
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
private void Start()
{
customer.OnOrder += waiter.TakeAction;//需要与委托类型保持一致
customer.Order("Mocha","Grand",32);//事件拥有者的内部逻辑,触发的事件
customer.Order("Makalong", "Tall", 16);
customer.PayTheBill();
}
}
public class Customer
{
public float Bill { get; set; }
public void PayTheBill()
{
Debug.Log("Pay:" + "$" + this.Bill);
}
public event EventHandler OnOrder;
public void Order(string _name,string _size,float _price)
{
if(OnOrder != null)//判断事件是否为空,语法糖
{
OrderEventArg e = new OrderEventArg();
e.CoffeeName = _name;
e.CoffeeSize = _size;
e.CoffeePrice = _price;
OnOrder(this, e);
}
}
}
//创建一个用来传递事件参数(事件信息、消息)属于EventArgs这个类,即名字:事件名 + EventArgs作为后缀
//派生自EventArgs这个类型,也是微软、厂商为我们准备好的一个基类
public class OrderEventArg : EventArgs
{
public string CoffeeName { get; set; }
public string CoffeeSize { get; set; }
public float CoffeePrice { get; set; }
}
public class Waiter
{
internal void TakeAction(object _sender, EventArgs _ea)
{
float finalPrice = 0;
Customer customer = _sender as Customer;
OrderEventArg e = _ea as OrderEventArg;
switch (e.CoffeeSize)
{
case "Tall":
finalPrice = e.CoffeePrice;//中杯:原价
break;
case "Grand":
finalPrice = e.CoffeePrice + 3;//大杯:原价+3
break;
case "Venti":
finalPrice = e.CoffeePrice + 6;//超大杯:原价+6
break;
}
customer.Bill += finalPrice;
}
}
分析错误
错误示范①:简略声明格式下,尝试抹去event。此时程序正常运作,不报错,输出正确的结果。此时发现,该委托类型的字段为public,谁都可以访问它的。它就会隐藏一些潜在的问题,—->借刀杀人
面试官提问一:委托和事件的关系?
不是委托类型字段,只是委托类型字段的包装器、限制器,限制外界对委托类型字段的访问。
委托类型的字段经过事件这么一包装、限制之后,外界只能去访问他的+=(添加)、-=(移除)操作符 事件处理器。
面试官提问二:为什么要使用委托类型来声明事件?(为什么事件是基于委托的?)