C#学习笔记-事件基础

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Event1
{
#if false
1、Event的普通定义就是“能够发生什么事情, a thing that happens, especially something important!2、C#中的事件的定义:使对象或类具备通知能力的成员
3、作用:用于对象或类间动作协调与信息传递(消息推送)
4、原理:事件模型(也叫“发生-响应”模型)
     5个部分:eg:闹钟响了你起床,可以分解为5部分:(1)闹钟(事件的发出者/拥有者 event source) (2)响铃(事件event,可以附带一些信息即事件参数) ---(3)订阅(subscribe 你关心了闹铃事件)--- (4)你(事件订阅者/响应者event subscriber) (5)起床(对事件的响应,也叫处理事件或事件处理器 event handler)
     5个动作:(1)我有一个事件 (2)一个人或一群人关心我这个事件 (3)我这个事件发生了 (4)关心这个事件的人会依次得到通知 (5)收到通知的人根据拿到的事件信息(又称事件参数/数据)对事件进行响应(处理事件)
5、常用场景
    GUI编程
    MVC MVP MVVM是事件模型的升级
    绝大部分情况下都不需要自己定义事件,都是使用预定义的事件
6、事件和委托的关系
    委托只是事件和事件处理器之间的的一种调用约定
#endif
    class Program
    {
        static void Main(string[] args)
        {
            // 类最重要的三个部分(存储数据、做事情、通知别人)
            // 属性:表示当前对象的状态
            // 事件:表示对象能在什么情况下通知谁
            // 方法:表示当前对象能做什么

#if true
            // 模型1 *:(事件的拥有者、事件) 和 (事件订阅者、事件处理器) 两大部分分别独立,这是最基础的模型,也是MVC这些模式的雏形
            // event source
            System.Timers.Timer timer = new System.Timers.Timer();  // Forms命名空间里面也有Timer,这里是为了解决冲突写明确指明是System.Timers下的Timer
            timer.Interval = 1000; // 1000ms
            // event subscribers
            Subscriber1 sub1 = new Subscriber1();
            Subscriber2 sub2 = new Subscriber2();
            // event --- +=(subscribe) --- event handler
            timer.Elapsed += sub1.TimerEventHandler;
            timer.Elapsed += sub2.TimerEventHandler;
            // event source开始工作,每隔1000ms发出Elapsed事件通知
            timer.Start();
#endif

#if true
            // 模型2 ***:(事件订阅者、事件处理器) 内部包含 (事件的拥有者、事件) ,这是典型的GUI中常用模型,
            // 比如 主窗口(按钮点击事件的订阅者)里面有一个按钮控件(event source) 订阅(subscribe) 按钮的点击事件(event) 并且拥有按钮点击事件的处理方法(event handler)
            MainForm mainForm = new MainForm();
            mainForm.ShowDialog();
#endif

#if false
            // 模型3 **:事件订阅者和拥有者是同一个对象,事件 和 事件处理器都属于该对象,即自己使用自己的事件处理器处理自己的事件
            MyForm form = new MyForm();
            form.Click += form.FormClicked;
            form.ShowDialog();
#endif

            Console.ReadLine();
        }
    }

    class Subscriber1
    {
        internal void TimerEventHandler(object sender, ElapsedEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Subscriber1 handing timer's elapsed event!");
        }
    }

    class Subscriber2
    {
        internal void TimerEventHandler(object sender, ElapsedEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Subscriber2 handing timer's elapsed event!");
        }
    }

    class MainForm : Form
    {
        public MainForm()
        {
            this.Text = "MainForm";
            this.Width = 400;
            this.Height = 300;
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;

            this.textBox = new TextBox();
            this.textBox.Top = 5;
            this.textBox.Width = this.Width - 10;
            this.textBox.Height = 25;

            this.button = new Button();
            this.button.Top = 10 + this.textBox.Height;
            this.button.Width = this.Width - 10;
            this.button.Text = "Button1";

            this.oldButton = new Button();
            this.oldButton.Top = this.button.Top + this.button.Height + 5;
            this.oldButton.Width = this.Width - 10;
            this.oldButton.Text = "Button2";

            this.Controls.Add(this.textBox);
            this.Controls.Add(this.button);
            this.Controls.Add(this.oldButton);

            // MainForm 订阅 button成员 的 Click 事件 安装的事件处理器为 ButtonClicked
            this.button.Click += this.ButtonClicked;


            // 一些事件处理器的旧式写法即显式使用委托的方式
            //this.oldButton.Click += new EventHandler(OldButton_Click); // EventHandler是一个委托类型,现在直接传一个方法给它也将自动生成对应的委托,就跟上面那样
            //this.oldButton.Click += delegate (object sender, EventArgs e)
            //{
            //    // 这说白了就是个匿名委托
            //    this.textBox.Text = "MainForm's Button2 Clicked!";
            //};

            // 新式的Lambda表达式,甚至可以不写参数的类型,编译器会根据Click事件处理器对应的委托约束 (选中Click按下F12可以跳转) 来正确推导类型
            this.oldButton.Click += (object sender, EventArgs e) =>
            {
                this.textBox.Text = "MainForm's Button2 Clicked!";
            };
        }

        private void OldButton_Click(object sender, EventArgs e)
        {
            this.textBox.Text = "MainForm's Button2 Clicked!";
        }

        // 按钮点击事件的处理器
        private void ButtonClicked(object sender, EventArgs e)
        {
            this.textBox.Text = "MainForm's Button1 Clicked!";
        }

        private TextBox textBox;
        private Button button; // 事件的拥有者event source,它是事件订阅者MainForm的一个成员
        private Button oldButton;
    }

    class MyForm : Form
    {
        internal void FormClicked(object sender, EventArgs e)
        {
            MessageBox.Show("Form Clicked!");
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Event2
{
    class Program
    {
        static void Main(string[] args)
        {
            // 事件拥有者
            Customer customer = new Customer();

            // 事件订阅者
            Water water = new Water();

            // 订阅事件、添加事件处理器
            customer.Order += water.Action;
            // customer.Order.Invoke // error 这就是为什么需要事件的原因,如果Order是一个委托,则它可以在外面任意调用,但是事件类型在外部是只能出现在 += 左边,不允许其他操作
            // 此时如果是委托,那么别的一个顾客就可以帮一个不认识的顾客瞎点菜,即 customer2.Order.Invoke(customer, e);

            // 由事件拥有者在某些条件下触发事件
            customer.Action();
            customer.PayTheBill();
        }
    }

    public class OrderEventArgs : EventArgs
    {
        public string DishName { get; set; }
        public string Size { get; set; }
    }


    // 约束事件和事件处理器的委托类型(即约束返回值、参数)
    public delegate void OrderEventHandler(Customer sender, OrderEventArgs e); 


    // 事件拥有者
    public class Customer
    {
#if false
        // 完整声明形式:

        // 用于保存事件处理器(处理器也是受 OrderEventHandler 委托类型约束)
        private OrderEventHandler orderEventHandler;

        // 声明事件(使用 OrderEventHandler 委托类型作为约束条件)
        public event OrderEventHandler Order
        {
            add
            {
                this.orderEventHandler += value; // 添加事件处理器
            }

            remove
            {
                this.orderEventHandler -= value;// 删除事件处理器
            }
        } 
#endif

        // 事件的简单声明形式(编译器在后台自动创建了OrderEventHandler委托类型的字段)
        public event OrderEventHandler Order;

        public double Bill { get; set; }

        public void PayTheBill()
        {
            Console.WriteLine("Pay the bill ${0}", this.Bill);
        }

        public void WalkIntoRestaurant()
        {
            Console.WriteLine("Customer walk into the restaurant...");
        }

        public void SitDown()
        {
            Console.WriteLine("Customer sit down...");
        }

        public void BrowseDishMenu()
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            for (int i = 0; i < 5; ++i)
            {
                Console.WriteLine("Browsing and choosing...");
                Thread.Sleep(1000);
            }

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Choose ok! Need a water...");

#if false
            // 使用完整声明时:
            // 判断是否有事件处理器
            if (this.orderEventHandler != null)
            {
                OrderEventArgs e = new OrderEventArgs() { DishName = "Kongpao Chicken", Size = "normal" };
                this.orderEventHandler.Invoke(this, e); // 触发事件
            }
#endif

            // 使用简单声明时
            if (this.Order != null)
            {
                OrderEventArgs e = new OrderEventArgs() { DishName = "Kongpao Chicken", Size = "normal" };
                this.Order.Invoke(this, e); // 触发事件
            }
        }

        public void Action()
        {
            WalkIntoRestaurant();

            SitDown();

            BrowseDishMenu();
        }
    }


    // 事件订阅者
    public class Water
    {
        public void Action(Customer customer, OrderEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.WriteLine("Water: a new dish:{0}", e.DishName);

            double price = 10.0;

            switch (e.Size)
            {
                case "small":
                    price = price * 0.5;
                    break;
                case "normal":
                    price = price * 1.0;
                    break;
                case "big":
                    price = price * 1.5;
                    break;
                default:
                    break;
            }

            customer.Bill += price;
        }
    }
}
原文地址:https://www.cnblogs.com/djh5520/p/14680161.html