是什么?
想象你有一个万能遥控器,可以控制家里的电视、空调、灯光。委托就是这个“遥控器”,它允许你通过一个东西调用多个不同的方法。
为什么需要它?
比如你想写一个程序,让用户点击按钮时执行某些操作,但具体操作可能随时变化。委托可以帮你灵活地“保存”这些操作,随时调用。
怎么用?
步骤 1:定义一个遥控器(委托)
步骤 2:创建具体设备(方法)
步骤 3:用遥控器绑定设备
//1、声明一个委托类型,它只能“控制”无返回值、参数为string的方法
public delegate void MyRemoteControl(string msg);
//2、创建具体设备(方法)
public void TurnOnTv(string msg){
Console.WriteLine("打开电视:"+msg);
}
public void TurnOffLight(string msg)
{
Console.WriteLine("关闭灯光:" + msg);
}
//3、用遥控器绑定设备
void Main()
{
// 绑定到电视
MyRemoteControl myRemote =new MyRemoteControl(TurnOnTv);
myRemote ("播放喜洋洋与灰太狼");
//多播:遥控器同时控制多个设备
myRemote+=TurnOffLight;
myRemote("睡觉&看球赛");
}
打开电视:播放喜洋洋与灰太狼
打开电视:睡觉&看球赛
关闭灯光:睡觉&看球赛
是什么?
事件是委托的升级版。比如你家门铃(事件),别人只能按门铃(触发事件),但不能直接拆掉你的门铃线路(保证安全)。
为什么需要它?
安全:外部代码只能订阅(+=)或取消订阅(-=),不能直接清空所有绑定。
场景:比如游戏中的“玩家死亡时通知所有敌人停止攻击”。
怎么用?
//步骤 1:定义一个门铃(事件)
public class Doorbell{
//声明一个事件(基于委托)
public event Action<string> OnRing;
public void Ring(){
//出发时间(按门铃)
OnRing?.Invoke("有人按门铃啦");// ?. 防止未订阅时出错
}
}
//步骤 2:住户的反应(订阅事件)
public class Resident{
public void ReactToRing(string msg){
Console.WriteLine("住户:"+msg+"我去开门!");
}
}
//步骤 3:使用门铃
void Main()
{
Doorbell doorbell = new Doorbell();
Resident resident = new Resident();
//住户订阅门铃时间
doorbell.OnRing +=resident.ReactToRing;
//有人按门铃
doorbell.Ring();
}
住户:有人按门铃啦我去开门!
?.
安全检查,等价于
if (OnRing != null) {
OnRing.Invoke(...);
}
Invoke
:正式“触发事件”
是什么?
假设你在煮饭(主线程),同时还要切菜(子线程)。多线程就是让程序能“同时”处理多个任务,提升效率。
为什么需要它?
防止主界面卡死(比如下载文件时不冻结界面)。
充分利用CPU多核性能。
怎么用?
//方法 1:传统方式(Thread)—— 手动控制
void Main()
{
Thread thread = new Thread(() => {
Console.WriteLine("子线程:我在切菜");
});
thread.Start();
Console.WriteLine("主线程:我在煮饭");
}
主线程:我在煮饭
子线程:我在切菜
//方法 2:现代方式(Task)—— 更简单高效
void Main()
{
Task.Run(() =>
{
Console.WriteLine("子线程:我在烧水!");
});
Console.WriteLine("主线程:我在炒菜!");
}
主线程:我在炒菜!
子线程:我在烧水!
//方法 3:异步编程(async/await)—— 等待不阻塞
public async Task CookDinner(){
Console.WriteLine("开始做饭");
//异步煮饭(不阻塞)
await Task.Run(() =>{
Thread.Sleep(2000);//2s
Console.WriteLine("饭煮好了");
});
Console.WriteLine("开始炒菜");//煮晚饭开始
//await CookDinner();//调用
}
async Task Main(){
await CookDinner();
}
开始做饭
饭煮好了
开始炒菜
() => {}
这是一个 Lambda 表达式,相当于快速写一个“匿名方法”。
()
:参数列表(无参数时留空)。
=>
:箭头符号,表示“执行后面的代码”。
{}
:代码块,具体要执行的任务。
Thread thread = new Thread(() => {
Console.WriteLine("切菜");
}); // 直接把任务写在括号里
相当于:
void CutVegetables() {
Console.WriteLine("切菜");
}
Thread thread = new Thread(CutVegetables); // 传入方法名
委托和事件的区别?
委托是功能基础,事件是加了限制的委托(类似public和private的区别)。
多线程会加快程序速度吗?
不一定!如果任务简单,切换线程的开销可能反而更慢。适合处理耗时操作(如文件读写)。
async/await 和 Task 的区别?
async/await 是基于 Task 的语法糖,让异步代码看起来像同步代码,更易读。