首页 > 其他分享 >委托+事件

委托+事件

时间:2022-12-02 22:11:32浏览次数:46  
标签:Console 委托 void public 事件 class

1、事件简介      MVC、MVP、MVVM等模式,是事件模式更高级、更有效的“玩法”。
事件是在委托类型变量前加上event关键字,其本质是用来对委托类型的变量进行封装,类似于类的属性对字段的封装。
事件相当于增强了委托的封装性,以保证委托类型的变量在类外部不能被直接调用。这样相当于无论是在类的内部声明public还是protected的委托类型变量,只要用事件event进行封装,其效果都相当于声明了一个私有的委托类型变量。

注意:委托是(先有委托的声明,定义委托的类型,再有该类型的字段声明)

 

 

2、事件与委托的区别
        在注册和注销事件上,委托可以使用=和+=来将函数注册到委托的变量上,使用-=来将函数注销。而事件则有着更严格的限制,事件只能使用+=来将函数注册到其上,使用-=来将函数注销。
       事件类型的委托变量(即用事件封装的委托类型变量),在外部不能直接当成其引用的函数来进行调用,因为其相当于私有的委托类型变量,但特殊在于它在外部只能用于注册或注销函数,而公有的委托类型在外部是可以直接用来调用对应的注册函数。
        在此,事件和私有类型的委托变量的区别就在于:私有类型的委托变量在类外部是无法直接访问的,而事件相对于私有类型的委托变量又稍微多了一点点特例,就是事件可以在类外部被直接访问,但只能放在左边用来注册或注销函数。除此之外,它们用法相同,如都不能在类外部直接调用对应的注册函数等。如下图在类外部的主函数中调用示例:

 

4、具体应用

…………………………………………………………实例1

 using System;

namespace Pr01_Basic
{
class Program
{
static void Main(string[] args)
{
Publisher pub = new Publisher();
Subscriber sub = new Subscriber();

// 1、通过事件发布器来触发事件,然后订阅器接收该事件
pub.NumChange += new NumCountChange(sub.OnNumChange);
pub.InvokeEvent(); //发布者触发事件,订阅者接收该触发事件

// 2、通过委托则可以在外部直接触发该事件,为可行但不合理的方式
pub.NumChangeDelegate = new NumCountChange(sub.OnNumChange);
pub.NumChangeDelegate(200);//委托变量直接调用了订阅者的OnNumChange函数

Console.ReadKey();
}
}

/// <summary>
/// 声明委托类型
/// </summary>
/// <param name="num"></param>
public delegate void NumCountChange(int num);


/// <summary>
/// 事件发布者类
/// </summary>
class Publisher
{
public NumCountChange NumChangeDelegate; //声明委托类型变量

public event NumCountChange NumChange; //声明事件

public int count { set; get; } = 99;

//当调用该函数时,由发布者来触发对应的事件
public void InvokeEvent()
{
if(NumChange != null) //当委托中有函数注册时(即为非空),就会触发该事件
{
++count;
NumChange(count);//触发该事件
}
}

}

/// <summary>
/// 事件订阅者类
/// </summary>
class Subscriber
{
//该函数会注册到委托事件中,一旦事件发布者触发该事件时,订阅者就会接收到该事件进行执行
public void OnNumChange(int count)
{
Console.WriteLine("Subscriber the changed number is {0}", count);
}

}

}

 …………………………………………………………

 …………………………………………………………实例2

using System;
using System.Threading;

 

namespace Pr02_Delegate
{
class Program
{
static void Main(string[] args)
{
Heater heater = new Heater();
Alarm alarm = new Alarm();
Display display = new Display();

 

heater.curTemperature += alarm.MakeAlarm; //将报警函数注册到事件上
heater.curTemperature += display.ShowTemperature; //将显示温度函数注册到事件上

 

heater.Heating();//开始加热

 

}
}

 

public delegate void SendTemperatureEvent(int num);

 

/// <summary>
/// 加热器:负责加热。相当于事件发布者,用来发布当前水温。
/// </summary>
class Heater
{
public event SendTemperatureEvent curTemperature;

 

private int temperature;
private int maxTemp = 100;

 

public void Heating()
{
//水温从85度开始
for(int i=85;i<=maxTemp;++i)
{
temperature = i;

 

if(curTemperature!=null)
{
curTemperature(temperature);
}

Thread.Sleep(100);
}

 

Console.WriteLine("Now the temperatue is up to 100 °C !!!");
Console.ReadKey();
}

 


}

 

/// <summary>
/// 报警器:当水温达到一定的值时,进行报警
/// </summary>
class Alarm
{
//订阅者:从加热器那里订阅水温,当水温达到一定值,就开始报警。
public void MakeAlarm(int temperature)
{
if(temperature>90)
{
Console.WriteLine("The temperature is up to {0}", temperature);
}
}
}

 

/// <summary>
/// 显示器:显示水温值
/// </summary>
class Display
{
//订阅者:从加热器那里订阅水温,并进行显示。
public void ShowTemperature(int temperature)
{
Console.WriteLine("The temperature = {0}", temperature);
}
}
}

 

  …………………………………………………………

  …………………………………………………………实例3

 

using System;
using System.Threading;

namespace 事件_完整声明
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;
customer.Action();//触发这个事件
customer.PayTheBill();
}
}
//事件信息,命名规范:事件名+EventArgs
//事件信息这个类必须继承自EventArgs,记住就行
public class OrderEventArgs:EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
//委托用来声明事件时
//命名规范:事件名+EventHandler
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);
public class Customer
{
public OrderEventHandler orderEventHandler;
//声明事件,event是声明事件关键字
public event OrderEventHandler Order
{
add
{
this.orderEventHandler = value;
}
remove
{
this.orderEventHandler = value;
}
}
public double Bill { get; set; }
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}.",this.Bill);
}
//下面几个方法用来触发事件
public void Walkln()//进店
{
Console.WriteLine("Walk into the restaurant.");
}
public void SitDown()//坐下
{
Console.WriteLine("Sit down");
}
public void Think()//思考吃什么
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
if(orderEventHandler!= null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao Chicken";
e.Size = "large";
//触发事件处理器
this.orderEventHandler.Invoke(this, e);
}
}
public void Action()
{
Console.ReadLine();
this.Walkln();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(Customer customer, OrderEventArgs e)
{
Console.WriteLine("I will serve you the dish {0}",e.DishName);
double price = 10;
switch(e.Size)
{
case "small":
price *= 0.5;
break;
case "large":
price *= 1.5;
break;
default:
break;
}
customer.Bill += price;
}
}
}

 

  …………………………………………………………

  ………………………………………………………… 实例4(EventHandler)

 

 

 

 

using System;
using System.Threading;

namespace 事件_简略声明
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;
customer.Action();
customer.PayTheBill();
}
}
public class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
public class Customer
{
public event EventHandler Order;       // 不需要再次进行委托声明
public double Bill { get; set; }
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}.", this.Bill);
}
public void Walkln()
{
Console.WriteLine("Walk into the restaurant.");
}
public void SitDown()
{
Console.WriteLine("Sit down");
}
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
if (Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao Chicken";
e.Size = "large";
this.Order.Invoke(this, e);
}
}
public void Action()
{
Console.ReadLine();
this.Walkln();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(object sender, EventArgs e)
{
Customer customer = sender as Customer;
OrderEventArgs orderInfo = e as OrderEventArgs;
Console.WriteLine("I will serve you the dish {0}", orderInfo.DishName);
double price = 10;
switch (orderInfo.Size)
{
case "small":
price *= 0.5;
break;
case "large":
price *= 1.5;
break;
default:
break;
}
customer.Bill += price;
}
}
}

 

…………………………………………………………

标签:Console,委托,void,public,事件,class
From: https://www.cnblogs.com/ZBO123/p/16943102.html

相关文章

  • iPayLinks艾贝盈上线委托换汇功能!
    “8.11”汇改以来,人民币汇率市场化形成机制逐步完善,人民币汇率弹性不断增强,双向波动成为常态。在市场化的汇率形成机制下,外贸人想要快、准、稳地选到合适汇率,降低汇损提高利......
  • 什么样的事件会符合正太分布(如何直观判断是否是正太分布)
     1. 影响该事件的因素有无穷多个,而每个因素的影响又是无穷小,那么这个事件就服从正态分布;如果服从正态分布的随机变量它的均值为零、标准差为1,那么这个变量就服从标......
  • 事件绑定on与hover事件
    鼠标划入和划出的效果,本来这个小效果是非常简单的!可是在实际的生产环境中就出现了一点点问题!因为在实际的环境中,数据全部是用ajax异步加载进去的,这样就造成了hover方法不能......
  • 事件和键盘鼠标的修饰符
    一:事件处理解决点1.绑定事件2.事件传参3.保证事件的event不丢<template><div>欢迎来到上海</div><button@click="showInfo">点击提示信息</bu......
  • Android实验——事件处理:显示持续触摸时间
    一、实验要求和目的掌握基于监听的事件处理机制,根据需求能够编写相应的事件处理程序。能够熟练应用各种布局管理器和控件进行界面设计。二、实验环境部署有Android......
  • 遇到大事件、沉痛悼念时怎么把网站改成黑白
    在html标签增加一个style即可<htmlstyle="filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);-webkit-filter:grayscale(100%);">刚刚查了一下,发......
  • [Vue3-09]事件处理
    1.传参2.多事件绑定......
  • MASA Framework 事件总线 - 跨进程事件总线
    概述跨进程事件总线允许发布和订阅跨服务传输的消息,服务的发布与订阅不在同一个进程中在MasaFramework中,跨进程总线事件提供了一个可以被开箱即用的程序Integrati......
  • C# 委托
    C#中的委托(Delegate)类似于C或C++中函数的指针。委托(Delegate)是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托就是用来储存方法的结构委托......
  • 大数据学习10之分布式事件流平台Kafka——Kafka部署及使用
    文章目录​​准备1:zookeeper下载与安装​​​​1.下载zookeeper,解压,并配置到系统环境变量中`~/.bash_profile`中​​​​2.home/hadoop/app/zookeeper-3.4.5-cdh5.7.0/con......