c#委托和事件
事件是一种类型成员
事先是一种使对象或者类,能够提供通知的成员。
事件可以“发生”,通知别人,发生后的效果,才是事件的功能。
当这个事件发生后, 关系这个事件的其他类,对象们就会被依次通知到,这些对象也会根据这个事件以及事件夹杂的【事件参数】纷纷作出相应。
事件模型的五个组成部分
1.事件的拥有者
2.事件
3.事件的响应者
4.事件处理器
5.事件订阅(+=操作符)
事件处理器,它必须和事件遵守同一个【约定】,即是委托类型。
这个约定既约束了事件可以把什么样的消息,传递给事件处理器。
也约束了事件处理器,能够处理什么样的消息。
声明事件的时候会使用委托类型。
so常说事件是基于委托的:
1.类型兼容
2.存储方法的引用(通过委托去储存方法 )
事件不能够直接在外部直接调用。
事件完整声明格式:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
customer.OnOrder += waiter.TakeAction;
customer.Order();
customer.PayTheBill();
}
private Customer customer = new Customer();
private Waiter waiter = new Waiter();
/// <summary>
/// 事件模型的五个组成部分
/// 事件的拥有者【类】 Customer类
/// 事件【event关键字修饰】OnOrder,点餐事件
/// 事件的接收者【类】 Waiter类
/// 事件处理器【类的方法成员--受到约束的方法】TakeAction方法
/// 事件的订阅关系【+=】 +=
/// </summary>
//为OnOrder事件声明委托类型
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);
public class OrderEventArgs : EventArgs
{
public string coffeeName { get; set; }
public string coffeeSize { get; set; }
public float coffeePrice { get; set; }
}
public class Customer
{
public float Bill { get;set; }
public void PayTheBill()
{
Debug.Log("I have to pay :"+this.Bill);
}
/// <summary>
/// 事件的完整声明格式
/// </summary>
private OrderEventHandler orderEventHandler;
public event OrderEventHandler OnOrder
{
add
{
orderEventHandler += value;
}
remove
{
orderEventHandler -= value;
}
}
public void Order()
{
//等于null表示没有人去订阅这个事件(没有储存任何方法的引用)
if (orderEventHandler!=null)
{
OrderEventArgs e = new OrderEventArgs();
e.coffeeName = "mocha";
e.coffeeSize = "Tall";
e.coffeePrice = 28;
orderEventHandler(this,e);
OrderEventArgs e1 = new OrderEventArgs();
e1.coffeeName = "mocha";
e1.coffeeSize = "Venti";
e1.coffeePrice = 29;
orderEventHandler(this,e1);
}
}
}
public class Waiter
{
public void TakeAction(Customer customer, OrderEventArgs e)
{
float finalPrice = 0;
switch (e.coffeeSize)
{
case "Tall":
finalPrice = e.coffeePrice;
break;
case "Grand":
finalPrice = e.coffeePrice + 3;
break;
case "Venti":
finalPrice = e.coffeePrice + 6;
break;
}
customer.Bill += finalPrice;
}
}
}
面试问题:
事件是不是委托类型的字段?
是不是一种特殊类型的委托类型的字段呢?
答案:都不是。
事件简略声明格式:
/*/// <summary>
/// 事件的完整声明格式
/// </summary>
private OrderEventHandler orderEventHandler;
public event OrderEventHandler OnOrder
{
add
{
orderEventHandler += value;
}
remove
{
orderEventHandler -= value;
}
}*/
/// <summary>
/// 事件省略声明格式
/// </summary>
//public event OrderEventHandler OnOrder;
/// <summary>
/// 事件省略声明格式 使用EventHandler委托
/// </summary>
public event EventHandler OnOrder;
public void Order()
{
//等于null表示没有人去订阅这个事件(没有储存任何方法的引用)
if (OnOrder!=null)
{
OrderEventArgs e = new OrderEventArgs();
e.coffeeName = "mocha";
e.coffeeSize = "Tall";
e.coffeePrice = 28;
OnOrder(this,e);
OrderEventArgs e1 = new OrderEventArgs();
e1.coffeeName = "mocha";
e1.coffeeSize = "Venti";
e1.coffeePrice = 29;
OnOrder(this,e1);
}
}
【is操作符】检查对象是否与给定的类型兼容
【as操作符】用于检查在兼容的引用类型之间执行某些类型的转换。(如果不兼容也不会报错,返回null)
属性和事件都是包装器
属性是字段的包装器(作用是保护字段(变量)不被滥用,在set和get中,添加逻辑来保护字段);
事件是委托类型字段的包装器(作用是保护委托类型的字段不外界滥用,现实外界对内部委托字段的访问);
属性绝对不是字段
事件也绝对不是委托类型的字段