Cool_Breeze 发表于 2021-3-8 11:39

C# 学习笔记 完整事件声明 点餐示例

本帖最后由 Cool_Breeze 于 2021-3-8 16:26 编辑


using System;
using System.Threading;

namespace Restaurant
{
    class Program
    {
      static void Main()
      {
            string[] PeopleName = {"GIN", "Brezee", "Tom", "Tim", "Cool", "998"};
            Customer customer = new Customer(); // customer 事件的拥有者
            Waiter zeroOne = new Waiter(); // zeroOne 事件的响应者
            
            customer.EnterEventHandler += zeroOne.Welcome; // 进店事件订阅
            // customer.EnterEventHandler += zeroOne.WaiterTotal; // 事件订阅
            customer.OrderEventHandler += zeroOne.OrderHandler; // 点餐事件订阅
            customer.EndOfMealEventHandler += zeroOne.CollectMoney; // 买单事件订阅
            
            EatEventArgs people1 = new EatEventArgs("GIN");
            Random random = new Random();
            while (true)
            {
                people1.CustomerName = PeopleName[ random.Next(PeopleName.Length) ];
                customer.EnterTheStoreActivation(people1); // 顾客进店
               
                people1.OrderRandom(); // 初始化点餐信息
                customer.OrderActivation(people1); // 顾客点餐

                customer.EndOfMealEventHandlerActivation(people1); // 顾客买单
            }
      }
    }
   
   
    public class EatEventArgs : EventArgs
    {
      public string CustomerName {get; set;} // 客人名字
      public float Price {get; set;} // 消费金额
      public string DishName {get; set;} // 菜名
      public string Measure {get; set;} // 菜量:大份,小份。没有中份   
      public EatEventArgs(string name)
      {
            this.CustomerName = name;
      }
      
      
      private string[] DishNameList = {"小炒肉", "红烧肉", "蒜苗火锅肉", "酱肘子", "酸菜鱼", "水煮鱼片"};
      private string[] SizeList = {"Large", "Less"};
      private Random random = new Random();
      public void OrderRandom()
      {
            this.DishName = this.DishNameList[ this.random.Next(this.DishNameList.Length) ]; // 随机选择菜名
            this.Measure = this.SizeList[ this.random.Next(this.SizeList.Length) ]; // 随机选择份量
      }
    }
   
   
    public delegate void EatEventHandler(Customer obj, EatEventArgs e); // 事件类型声明 有两个参数
   
    public class Customer
    {
      private event EatEventHandler EnterTheStore; // 客人进店事件字段。 private 不想暴露给外部
      public event EatEventHandler EnterEventHandler // 进店事件属性
      {
            add
            {
                this.EnterTheStore += value;
            }
            remove
            {
                this.EnterTheStore -= value;
            }
      }
      
      public void EnterTheStoreActivation(EatEventArgs people) // 激活客人进店事件
      {
            Console.WriteLine("<客人>:{0} 进店", people.CustomerName);
            if (this.EnterTheStore != null) // 检查事件有没有被订阅
            {
                this.EnterTheStore(this, people);
            }
      }
      
      private event EatEventHandler Order; // 客人点餐事件字段
      public event EatEventHandler OrderEventHandler // 客人点餐事件属性
      {
            add
            {
                this.Order += value;
            }
            remove
            {
                this.Order -= value;
            }
      }
      
      public void OrderActivation(EatEventArgs people) // 客人开始点餐
      {
            for (byte i = 0; i < 5; i++)
            {
                Console.WriteLine("<客人>:等我看看菜单。。。");
                Thread.Sleep(1000);
            }
            
            Console.WriteLine("<客人>:来一份 {0}, 份量:{1}.", people.DishName, people.Measure);
            if (this.Order != null)
            {
                this.Order(this, people);
                Thread.Sleep(2000);
            }
      }
      
      private event EatEventHandler End;
      public event EatEventHandler EndOfMealEventHandler
      {
            add
            {
                this.End += value;
            }
            remove
            {
                this.End -= value;
            }
      }
      
      public void EndOfMealEventHandlerActivation(EatEventArgs people) // 客人买单
      {
            Console.WriteLine("<客人>:服务员买单。。。");
            if (this.End != null)
            {
                this.End(this, people);
            }
            else
            {
                Console.WriteLine("<客人>:跑路咯。。。");
            }
      }
    }
   
    public class Waiter
    {
      // 客人进店事件处理
      public void Welcome(object sender, EatEventArgs e)
      {
            Console.WriteLine("<服务员>:欢迎光临本店:{0}.", e.CustomerName);
            Console.WriteLine("<服务员>:我们这里所有的菜大份 五元, 小份 三元!");
            Console.WriteLine("<服务员>:您需要吃点什么?");
      }
      
      // 客人点餐事件处理
      public void OrderHandler(object sender, EatEventArgs e)
      {
            Console.WriteLine("<服务员>:您点了 {0}, 份量为:{1}.", e.DishName, e.Measure);
            Console.WriteLine("<服务员>:您请稍等!");
            // 悄悄的先把顾客的帐单记好
            switch (e.Measure)
            {
                case "Less":
                  e.Price = 3;
                  break;
                case "Large":
                  e.Price = 5;
                  break;
                default:
                  break;
            }
            Thread.Sleep(2000);
            Console.WriteLine("<服务员>:您的菜已经好了!请慢用!");
      }
      
      // 客人买单事件处理
      public void CollectMoney(object sender, EatEventArgs e)
      {
            Console.WriteLine("<服务员>:来了来了!!!");
            Thread.Sleep(2000);
            Console.WriteLine("<服务员>:您点了 {0}, 份量为:{1}.", e.DishName, e.Measure);
            Console.WriteLine("<服务员>:您总共消费 {0} 元!", e.Price);
            Console.WriteLine("<服务员>:等待客户付款 {0} 元", e.Price);
            Console.WriteLine("<服务员>:收到顾客 {0} 的消费款 {1} 元!", e.CustomerName, e.Price);
            Console.WriteLine("<服务员>:{0} 欢迎下次光临!", e.CustomerName);
            Console.WriteLine("<本次服务结束>:------------- End -------------");
      }
      
      public void WaiterTotal(object sender, EatEventArgs e)
      {
            // 事件处理器可以 根据传入 sender 对象或者 sender 的某些属性, 使用不同 事件处理
            // 一个事件可以被多个事件处理器订阅
            // 一个事件处理器可以订阅多个事件
            // 只要遵循相同的声明类型
            Console.WriteLine(sender);
      }
    }
}

输出信息:
<客人>:GIN 进店
<服务员>:欢迎光临本店:GIN.
<服务员>:我们这里所有的菜大份 五元, 小份 三元!
<服务员>:您需要吃点什么?
<客人>:等我看看菜单。。。
<客人>:等我看看菜单。。。
<客人>:等我看看菜单。。。
<客人>:等我看看菜单。。。
<客人>:等我看看菜单。。。
<客人>:来一份 红烧肉, 份量:Large.
<服务员>:您点了 红烧肉, 份量为:Large.
<服务员>:您请稍等!
<服务员>:您的菜已经好了!请慢用!
<客人>:服务员买单。。。
<服务员>:来了来了!!!
<服务员>:您点了 红烧肉, 份量为:Large.
<服务员>:您总共消费 5 元!
<服务员>:等待客户付款 5 元
<服务员>:收到顾客 GIN 的消费款 5 元!
<服务员>:GIN 欢迎下次光临!


Cool_Breeze 发表于 2021-3-9 09:53

抱歉! 前面写的笔记有误,这里澄清一下!
using System;

namespace EventOne
{
    class Program
    {
      static void Main(string[] args)
      {
            Square square = new Square(); // 事件的拥有者
            
            Boy boy = new Boy();      // 事件的响应者(boy)
            Girl girl = new Girl();   // 事件的响应者(gril)

            HiEventArgs hiEventArgs = new HiEventArgs(boy); // 事件参数
            
            square.WhyEvent += boy.Sing; // 订阅事件
            square.WhyEvent += girl.Dance; // 订阅事件
            
            do
            {
                hiEventArgs.Unknown = boy;
                square.OnWhyEvent(hiEventArgs); // 事件发生
                hiEventArgs.Unknown = girl;
                square.OnWhyEvent(hiEventArgs); // 事件发生
                Console.ReadLine();
            } while (true);
      }
    }

    public delegate void HiEventHandler(Square sender, HiEventArgs e); // 事件类型声明, HiEventHandler 用来声明一个事件
   
    // 事件参数
    public class HiEventArgs : EventArgs
    {
      public object Unknown;
      public HiEventArgs(Boy boy) // 重载
      {
            this.Unknown = boy;
      }
      
      public HiEventArgs(Girl girl)
      {
            this.Unknown = girl;
      }
    }
   
    public class Square // 广场上
    {
      // 事件的完整声明
      private HiEventHandler why; // 事件 (他们都在干啥)
      public event HiEventHandler WhyEvent // 事件包装器,将 why 事件包护起来。
      {
            add
            {
                this.why += value;
            }
            remove
            {
                this.why -= value;
            }
      }
      
      // 事件放生只能在事件拥有者自己内部
      public void OnWhyEvent(HiEventArgs e) // 事件发生
      {
            // 按理说,事件只能出现在 += , -= 运算符旁边,不然会编译报错。但这里却可以吗,
            // 这里不是自相矛盾吗? 刘铁锰老师好像是说,微软自己的问题(语法糖吗?)
            if (this.why != null)
            {
                // this.why(this, e);
                this.why.Invoke(this, e);
            }
            else
            {
                Console.WriteLine("广场上空荡荡的!");
            }
      }
      
    }

    public class Boy
    {
      // 事件的处理器
      internal void Sing(object sender, HiEventArgs e)
      {
            if (e.Unknown == this) // 不关自己事
                Console.WriteLine("Boy SING");
      }
    }

    public class Girl
    {
      //事件处理器
      internal void Dance(object sender, HiEventArgs e)
      {
            if (e.Unknown == this)
                Console.WriteLine("girl Dance");
      }
    }
}

ak47f16200 发表于 2021-3-8 11:51

不错不错,收下,学习学习

xxl_hot 发表于 2021-3-8 12:04

不错不错

陈方方 发表于 2021-3-8 13:42

不错不错

egbert_tao 发表于 2021-3-8 13:47

不错不错,学习一下,感谢

7R903 发表于 2021-3-8 15:34

面向对象代码真好看,我写出来全是面向过程{:1_937:}

18970320484 发表于 2021-3-8 15:59

学习了学习了

Cool_Breeze 发表于 2021-3-8 16:36

cn005897 发表于 2021-3-8 15:34
面向对象代码真好看,我写出来全是面向过程

面向对象得好好学, 对自己提升很大!
页: [1]
查看完整版本: C# 学习笔记 完整事件声明 点餐示例