C#练习题——委托练习
一、任务一:用委托模拟做饭——>开饭——>吃饭的过程
(1)一家三口,妈妈做饭,爸爸妈妈和孩子都要吃饭
二、核心类结构分析
1. 抽象基类 - Person
abstract class Person
{public abstract void Eat();
}
定义抽象方法Eat(),强制所有子类实现吃饭行为
体现面向对象的抽象和多态特性
2. 具体实现类
Mother类 - 事件发布者
class Mother : Person
{public Action beginEat; // 关键:委托字段public override void Eat(){Console.WriteLine("妈妈吃饭");}public void DoFood(){Console.WriteLine("妈妈做饭");Console.WriteLine("妈妈做饭做好了");// 触发事件if (beginEat != null){beginEat(); // 执行所有注册的方法}}
}
Father和Son类 - 事件订阅者
class Father : Person
{public override void Eat(){Console.WriteLine("爸爸吃饭");}
}class Son : Person
{public override void Eat(){Console.WriteLine("孩子吃饭");}
}
三、委托机制详解
1. 委托定义
public Action beginEat;
使用
Action
委托,表示无参数无返回值的方法作为事件通知机制的核心
2. 订阅机制
m.beginEat += f.Eat; // 爸爸订阅
m.beginEat += s.Eat; // 孩子订阅
m.beginEat += m.Eat; // 妈妈自己也订阅
使用
+=
操作符实现多播委托支持多个方法的注册
3. 事件触发
if (beginEat != null)
{beginEat(); // 统一通知所有订阅者
}
空值检查避免异常
一句调用触发所有注册方法
四、任务一完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Xml.Linq;namespace 进阶测试
{abstract class Person{public abstract void Eat();}class Mother : Person{public Action beginEat;public override void Eat(){Console.WriteLine("妈妈吃饭");}public void DoFood(){Console.WriteLine("妈妈做饭");Console.WriteLine("妈妈做饭做好了");//执行委托函数if (beginEat != null){beginEat();}}}class Father : Person{public override void Eat(){Console.WriteLine("爸爸吃饭");}}class Son : Person{public override void Eat(){Console.WriteLine("孩子吃饭");}}class Program{static void Main(string[] args){Mother m = new Mother();Father f = new Father();Son s = new Son();//告诉妈妈 一会做好了 我要吃m.beginEat += f.Eat;m.beginEat += s.Eat;m.beginEat += m.Eat;//做饭m.DoFood();}}
}
五、任务二:用委托来模拟数据处理
(1)怪物死亡后,玩家要加10块钱
(2)界面要更新数据,成就要累加怪物击杀
数
六、核心架构设计
1. 事件中心 - Monster类(事件发布者)
class Monster
{public Action<Monster> deadDoSomthing; // 关键委托:死亡事件public int money = 10; // 怪物价值public void Dead(){Console.WriteLine("怪物死亡");if (deadDoSomthing != null){deadDoSomthing(this); // 触发事件,传递自身引用}deadDoSomthing = null; // 事件处理后清空委托}
}
使用
Action<Monster>
泛型委托,传递怪物实例本身空值检查避免空引用异常
事件触发后清空委托,防止重复触发
2. 事件订阅者 - 三个子系统
Player类(玩家系统)
class Player
{private int myMoney = 0;public void MonsterDeadDoSomthing(Monster m){myMoney += m.money; // 增加金钱Console.WriteLine("现在有{0}元钱", myMoney);}
}
Panel类(界面系统)
class Panel
{private int nowShowMoney = 0;public void MonsterDeadDo(Monster m){nowShowMoney += m.money; // 更新界面显示Console.WriteLine("当前面板显示{0}元钱", nowShowMoney);}
}
CJ类(成就系统)
class CJ
{private int nowKillMonsterNum = 0;public void MonsterDeadDo(Monster m){nowKillMonsterNum += 1; // 累计击杀数Console.WriteLine("当前击杀了{0}怪物", nowKillMonsterNum);}
}
七、完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;namespace 进阶测试
{//怪物死亡后,玩家要加10块钱,界面要更新数据//成就要累加怪物击杀数,请用委托来模拟实现这些功能//只用写核心逻辑表现这个过程,不用写的太复杂class Monster{//当怪物死亡时 把自己作为参数传出去 public Action<Monster> deadDoSomthing;//怪物成员变量 特征 价值多少钱public int money = 10;public void Dead(){Console.WriteLine("怪物死亡");if (deadDoSomthing != null){deadDoSomthing(this);}//一般情况下 委托关联的函数 有加 就有减(或者直接清空)deadDoSomthing = null;}}class Player{private int myMoney = 0;public void MonsterDeadDoSomthing(Monster m){myMoney += m.money;Console.WriteLine("现在有{0}元钱", myMoney);}}class Panel{private int nowShowMoney = 0;public void MonsterDeadDo(Monster m){nowShowMoney += m.money;Console.WriteLine("当前面板显示{0}元钱", nowShowMoney);}}class CJ{private int nowKillMonsterNum = 0;public void MonsterDeadDo(Monster m){nowKillMonsterNum += 1;Console.WriteLine("当前击杀了{0}怪物", nowKillMonsterNum);}}class Program{static void Main(string[] args){Monster monster = new Monster();Player p = new Player();Panel panel = new Panel();CJ cj = new CJ();monster.deadDoSomthing += p.MonsterDeadDoSomthing;monster.deadDoSomthing += panel.MonsterDeadDo;monster.deadDoSomthing += cj.MonsterDeadDo;monster.Dead();monster.Dead();Monster monster2 = new Monster();monster2.deadDoSomthing += p.MonsterDeadDoSomthing;monster2.deadDoSomthing += panel.MonsterDeadDo;monster2.deadDoSomthing += cj.MonsterDeadDo;monster2.Dead();}}
}