.Net之美读书笔记3
委托
委托的定义
委托(delegate)可以理解为函数类型,实现了函数可以当作参数传递,使程序更加灵活。下面通过代码快速熟悉委托的使用顺序。
//1. 声明委托类型
public delegate void GreetingDelegate(string name);
class Program
{
//2.定义委托方法体
public static void EnglishGreeting(string name)
{
Console.WriteLine("Morning," + name);
}
public static void ChineseGreeting(string name)
{
Console.WriteLine("早上好," + name);
}
public static void GreetPeople(string name, GreetingDelegate markGreet)
{
//4.调用委托
markGreet(name);
}
static void Main(string[] args)
{
//3.将函数赋值给委托
GreetPeople("Jerry Zhao", EnglishGreeting);
GreetPeople("番茄赵", ChineseGreeting);
Console.ReadKey();
}
事件
事件(event):对委托的封装,保护委托不允许外部程序直接为委托赋值(会将已添加的委托丢掉)。
使用方法public event GreetingDelegate MarkGreet;
.Net事件模型
这里借助一个熟悉的例子讲诉事件模型。热水器烧水到95后,报警器报警,显示器显示。
/// <summary>
/// 加热器
/// </summary>
public class Heater
{
private int temperature;
/// <summary>
/// 型号
/// </summary>
public string type = "RealFire 001";
/// <summary>
/// 产地
/// </summary>
public string area = "China Xian";
/// <summary>
/// 委托
/// </summary>
/// <param name="sender">被观察者(Heater)</param>
/// <param name="e">传递到观察者的参数</param>
public delegate void BoiledEnentHandler(object sender, BoiledEventArgs e);
/// <summary>
/// 初始化空函数,防止没有订阅值为null,调用报错
/// </summary>
public event BoiledEnentHandler Boiled = (sender, e) => { };
/// <summary>
/// 注意这里使用内部类,只是传递参数
/// 被观察着传入到观察者参数
/// </summary>
public class BoiledEventArgs : EventArgs
{
public readonly int temperature;
public BoiledEventArgs(int temperature)
{
this.temperature = temperature;
}
}
/// <summary>
/// 被观察者通知观察者方法
/// </summary>
/// <param name="e">参数</param>
protected virtual void OnBoiled(BoiledEventArgs e)
{
//#1多播委托
/*
foreach(Delegate d in Boiled.GetInvocationList())
{
BoiledEnentHandler boiled = (BoiledEnentHandler)d;
boiled(this, e);
}
*/
//#2异常处理,一个主题有多个订阅者。订阅者一个订阅者发出异常不应该阻塞其他订阅者
/*
foreach (Delegate d in Boiled.GetInvocationList())
{
BoiledEnentHandler boiled = (BoiledEnentHandler)d;
try
{
boiled(this, e);
}
catch (Exception ex)
{
}
}
*/
//#3超时处理,发布者不应这个通知订阅者,应采用一部调用
foreach (Delegate d in Boiled.GetInvocationList())
{
BoiledEnentHandler boiled = (BoiledEnentHandler)d;
boiled.BeginInvoke(this, e, null, null);
}
//Boiled(this, e);
}
/// <summary>
/// </summary>
public void BoilWater()
{
for (int i = 0; i <= 100; i++)
{
temperature = i;
if (temperature > 95)
{
BoiledEventArgs e = new BoiledEventArgs(temperature);
OnBoiled(e);
}
}
}
}
/// <summary>
/// 报警器
/// </summary>
public class Alarm
{
public void MarkAlert(object sender, Heater.BoiledEventArgs e)
{
Heater heater = (Heater)sender;
Console.WriteLine("Alarm:{0}-{1}", heater.area, heater.type);
Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度", e.temperature);
Console.WriteLine();
Thread.Sleep(500);
}
}
/// <summary>
/// 显示器
/// </summary>
public class Display
{
public static void ShowMsg(object sender, Heater.BoiledEventArgs e)
{
Heater heater = (Heater)sender;
if (e.temperature == 99)
{
Thread.Sleep(2000);
}
Console.WriteLine("Display:{0}-{1}", heater.area, heater.type);
Console.WriteLine("Display:水已经{0}度", e.temperature);
Console.WriteLine();
}
}
//调用
static void Main(string[] args)
{
Heater heater = new Heater();
Alarm alarm = new Alarm();
heater.Boiled += alarm.MarkAlert;
heater.Boiled += Display.ShowMsg;
heater.BoilWater();
Console.ReadKey();
}
委托进阶
利用上面的代码介绍下多播的进阶
- 1多播委托的调用
- 2异常处理,多播中异常处理
- 3超时处理,委托的异步调用成对出现 BeginXXX,EndXXX
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)