时间:2024/2/16来源:本站原创作者:佚名

我们先来设定这样一个场景:

公司的人事部门负责核算员工的工资,并在发放完工资以后通知每一位员工,员工收到工资以后可以去做自己喜欢的事情

用委托方式实现

先定义一个委托类型SalaryPaidDelegate,无参数,无返回值

publicdelegatevoidSalaryPaidDelegate();

定义一个人事部门类HRManager,负责发放工资和通知员工,代码如下

///summary///职责:///1.核算员工工资///2.发工资///3.通知员工工资已到账////summarypublicclassHRManager{//声明一个委托对象,当工资发放以后,通知员工publicSalaryPaidDelegate?OnSalaryPaid;///summary///支付工资方法////summarypublicvoidPaySalary(){//业务逻辑://1.核算员工工资//TODO://2.发工资//TODO://3.通知员工工资已到账Console.WriteLine("人事部通知:工资已发放!");//调用委托方法通知员工,员工需要先进行委托注册if(OnSalaryPaid!=null)OnSalaryPaid.Invoke();}}

再来定义两个员工类,EmployeeXiaoMing和EmployeeDaQiang

///summary///员工小明////summarypublicclassEmployeeXiaoMing{///summary///工资发放以后的回调方法,需要注册到HRManager对象的OnSalaryPaid中////summarypublicvoidOnSalaryPaid(){Console.WriteLine("我是小明,我收到工资了,下班带女朋友去吃大餐,看电影!");}}///summary///员工大强////summarypublicclassEmployeeDaQiang{///summary///工资发放以后的回调方法,需要注册到HRManager对象的OnSalaryPaid中////summarypublicvoidOnSalaryPaid(){Console.WriteLine("我是大强,我收到工资了,先还房贷,再还信用卡!");}}

在Main方法中,我们分别创建一个HRManager对象,两个员工对象EmployeeXiaoMing,EmployeeDaQiang,并让这两个员工对象注册一下HRManager对象的OnSalaryPaid委托。然后调用hrManager.PaySalary();

staticvoidMain(string[]args){HRManagerhrManager=newHRManager();EmployeeXiaoMingxiaoming=newEmployeeXiaoMing();EmployeeDaQiangdaqiang=newEmployeeDaQiang();//委托注册hrManager.OnSalaryPaid+=xiaoming.OnSalaryPaid;hrManager.OnSalaryPaid+=daqiang.OnSalaryPaid;//人事部发工资,然后内部调用委托方法来通知员工hrManager.PaySalary();}

输出结果:

人事部通知:工资已发放!我是小明,我收到工资了,下班带女朋友去吃大餐,看电影!我是大强,我收到工资了,先还房贷,再还信用卡!

现在小明和大强都收到通知了,整个流程很正常。

不过,这里有两个问题:

问题一:OnSalaryPaid委托可以在HRManager类的外部直接调用

staticvoidMain(string[]args){HRManagerhrManager=newHRManager();EmployeeXiaoMingxiaoming=newEmployeeXiaoMing();EmployeeDaQiangdaqiang=newEmployeeDaQiang();hrManager.OnSalaryPaid+=xiaoming.OnSalaryPaid;hrManager.OnSalaryPaid+=daqiang.OnSalaryPaid;//在外部直接调用了这个委托!!!hrManager.OnSalaryPaid.Invoke();}

本来应该只能在HRManager的内部调用,因为在调用委托之前,HRManager内部需要先执行一些业务逻辑,比如计算员工考勤,核算工资数额,提交财务审批,老板签字。。。,当这些步骤都完成了,才可以执行这个委托。

问题二:OnSalaryPaid委托在外部可以通过”=“操作符给委托赋值

比如,员工小明用”+=“注册了委托,员工大强在注册这个委托的时候,不小心把“+=”写成了“=”

hrManager.OnSalaryPaid+=xiaoming.OnSalaryPaid;//大强在注册委托方法的时候,不小心把“+=”写成了"="hrManager.OnSalaryPaid=daqiang.OnSalaryPaid

这样就覆盖了所有其他人注册的委托方法,只剩下了大强可以收到人事部发工资的通知:

人事部通知:工资已发放!我是大强,我收到工资了,先还房贷,再还信用卡!

小明和其他注册了委托方法的人完全不知道发生了什么!

应该怎么解决上面的两个问题呢?答案是:事件

用事件方式来实现

事件的方式很简单,只需要在声明委托对象前加一个event关键字

//加一个event关键字publiceventSalaryPaidDelegate?OnSalaryPaid;

当加上event关键字以后,如果在外部直接调用,就会显示错误提示。

同样,在外部也不能使用“=”,这样也就避免了外部误操作,或者试图在外部调用“OnSalaryPaid=null”清理所有委托方法。

总结:为什么使用事件而不是委托?

事件只能在内部触发,也就是只有事件的拥有者自己可以调用事件,这样避免了外部直接调用,提供了更好的封装。

在外部只能通过”+=“,”-=“来添加和移除事件,不能用“=”清空事件,只能在内部使用“=”,这样做对事件方法的注册提供了更好的保护。


转载请注明原文网址:http://www.helimiaopu.com/cxtx/cxtx/13017.html
------分隔线----------------------------