事件例子
因为这个例子太长了,不看的时候往下翻着麻烦,所以单独放进一篇笔记里
class Program
{
static void Main(string[] args)
{
Waiter waiter = new Waiter();
Customer Zhangsan = new Customer() { Name = "张三" };
Zhangsan.GoToRestaurant();
// 张三叫服务员点餐
Zhangsan.CallWaiter(waiter);
Zhangsan.OrderDish();
// 张三结账
Zhangsan.PayTheBill(waiter);
Customer LiSi = new Customer() { Name = "李四" };
LiSi.GoToRestaurant();
// 李四叫服务员点餐
LiSi.CallWaiter(waiter);
LiSi.OrderDish();
LiSi.Pay += waiter.ShowTheBill;
// 事件只能出现在 += 和 -= 的左边,不能出现在任何其他操作符的左边
// 且只能在事件拥有者的内部去触发事件
// 但由于Pay不是事件是委托,所以可以在外部invoke
// 导致李四把账记张三头上
LiSi.Pay.Invoke(Zhangsan);
}
}
class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
delegate void CallWaiterEventHandler(Customer customer);
delegate void PayEventHandler(Customer customer);
// 菜单
enum DishMenu
{
饺子 = 1,
面条,
炒饼,
盖浇饭,
};
/// <summary>
/// 顾客,喊服务员、点餐、结账事件的拥有者
/// </summary>
class Customer
{
// 顾客姓名
public string Name { get; set; }
// 声明委托类型字段,用来存储引用事件处理器
private CallWaiterEventHandler _callWaiter;
// 顾客叫服务员事件——完整声明
public event CallWaiterEventHandler CallWaiterEvent
{
add
{
_callWaiter += value;
}
remove
{
_callWaiter -= value;
}
}
// 顾客点餐事件——简略声明
public event EventHandler<OrderEventArgs> Order;
// 顾客付款用委托来做,没有用 event 约束,导致外界可以直接invoke
public PayEventHandler Pay;
/// <summary>
/// 顾客去饭馆吃饭
/// </summary>
public void GoToRestaurant()
{
Console.WriteLine($"{Name} 走进饭馆...");
Console.WriteLine();
}
/// <summary>
/// 顾客叫服务员点餐
/// </summary>
/// <param name="waiter">服务员对象</param>
public void CallWaiter(Waiter waiter)
{
// 喊服务员点餐, 即服务员订阅顾客的 喊服务员事件和点餐事件
// 顾客是事件的拥有者,服务员是事件的订阅者
_callWaiter += waiter.ShowMenu;
Order += waiter.Serve;
// 如果有服务员过来了,则触发顾客叫服务员事件,服务员展示菜单
if (_callWaiter != null)
{
_callWaiter.Invoke(this);
// 顾客思考吃啥
Thinking();
}
}
// 顾客思考吃啥
private void Thinking()
{
Console.WriteLine($"{Name}:");
for (int i = 0; i < 3; i++)
{
Console.WriteLine("\t我想想吃啥...");
Thread.Sleep(1000);
}
}
/// <summary>
/// 顾客点餐
/// </summary>
public void OrderDish()
{
// 如果有服务员订阅了点餐事件
// 即服务员正在等待顾客点餐, 则开始点餐
if (Order != null)
{
Console.WriteLine("我要吃(输入数字):");
int dishChoice = int.Parse(Console.ReadLine());
DishMenu dish = (DishMenu)dishChoice;
Console.WriteLine("份量是(小份/大份):");
int sizeChoice = int.Parse(Console.ReadLine());
string size = (sizeChoice == 0) ? "大份" : "小份";
// 触发顾客点餐事件
TriggerOrderDish(dish.ToString(), size);
}
}
// 触发顾客点餐事件的代码
private void TriggerOrderDish(string dishName, string size)
{
Order?.Invoke(this, new OrderEventArgs() { DishName = dishName, Size = size });
}
/// <summary>
/// 顾客结账
/// </summary>
/// <param name="waiter">服务员对象</param>
public void PayTheBill(Waiter waiter)
{
// 服务员订阅 + 触发顾客付款事件
Pay += waiter.ShowTheBill;
Pay?.Invoke(this);
}
}
/// <summary>
/// 服务员,喊服务员、点餐、结账事件的订阅者
/// </summary>
class Waiter
{
// 外界只能获取账单,不能修改
public double Bill { get; private set; }
private Customer _customer;
private OrderEventArgs _orderArgs;
/// <summary>
/// 喊服务员事件的事件处理器,向顾客展示菜单
/// </summary>
public void ShowMenu(object source)
{
Customer _customer = source as Customer;
Console.WriteLine($"欢迎光临,{_customer.Name}先生!这是我们的菜单:");
Console.WriteLine("1 --- 饺子\t--- 大份 15 元,小份 12 元");
Console.WriteLine("2 --- 面条\t--- 大份 10 元,小份 7 元");
Console.WriteLine("3 --- 炒饼\t--- 大份 10 元,小份 7 元");
Console.WriteLine("4 --- 盖浇饭\t--- 大份 12 元,小份 9 元");
Console.WriteLine("");
Console.WriteLine("0 --- 大份");
Console.WriteLine("其他数字 --- 小份");
Console.WriteLine("输入数字进行选择,按回车确认。");
Console.WriteLine("------------------");
}
/// <summary>
/// 点餐事件的事件处理器,向顾客上菜
/// </summary>
/// <param name="source">顾客对象</param>
/// <param name="e">顾客点餐事件参数</param>
public void Serve(object source, EventArgs e)
{
_customer = source as Customer;
_orderArgs = e as OrderEventArgs;
Console.WriteLine($"您好,{_customer.Name}先生,这是您点的 {_orderArgs.Size} {_orderArgs.DishName}。");
}
// 计算账单
private void CalculateBill()
{
// 先默认是大份
switch (_orderArgs.DishName)
{
case "饺子":
Bill = 15.0;
break;
case "面条":
Bill = 10.0;
break;
case "炒饼":
Bill = 10.0;
break;
case "盖浇饭":
Bill = 12.0;
break;
default:
break;
}
// 如果点的小份便宜3块钱
switch (_orderArgs.Size)
{
case "小份":
Bill -= 3;
break;
default:
break;
}
}
/// <summary>
/// 结账事件的事件处理器,向顾客展示账单
/// </summary>
/// <param name="source">顾客对象</param>
public void ShowTheBill(Object source)
{
_customer = source as Customer;
CalculateBill();
Console.WriteLine($"\n{_customer.Name} 先生,您一共消费了 {Bill} 元.\n");
}
}
- 运行结果
