C#中为什么用事件代替委托?
为什么我们要在C#中用事件代替委托?能不能只使用委托?为什么要使用事件?今天这篇文章就分析一下为什么使用事件的主要原因。
将代码分发给团队开发端和团队客户端,开发端编写了委托代码,客户端将实例化并订阅到委托。
团队开发端
首先,我们只使用委托编写如下代码:
1 public delegate void YourLoggingHere(); 2 public class WhyUseEvents 3 { 4 public YourLoggingHere MyLogging; 5 public void MyMainProgram() 6 { 7 ExecuteValidation(); 8 } 9 10 private void ExecuteValidation() 11 { 12 //Execution of validation and logic here 13 //With some business rules etc. 14 15 if (MyLogging != null) 16 { 17 MyLogging.Invoke(); 18 } 19 } 20 }
如上所示,开发端声明了“YourLoggingHere”委托,声明委托变量“MyLogging”。现在,客户端可以实例化这个类,使用委托变量并添加函数方法。
团队客户端
在下面的示例中,客户端想要使用类并添加函数方法到“MyLogging”委托。他们可以添加很多想要添加的函数方法。在这个示例中,他们只添加了一个函数方法,如下:
1 WhyUseEvents why = new WhyUseEvents(); 2 why.MyLogging += () => 3 { 4 Console.WriteLine("Hi I am subscribing to the delegate."); 5 };
现在开发端和客户端都能使用这些代码。但是,奇怪的是,客户端能直接调用委托。
1 WhyUseEvents why = new WhyUseEvents(); 2 why.MyLogging += () => 3 { 4 Console.WriteLine("Hi I am subscribing to the delegate."); 5 }; 6 7 why.MyLogging.Invoke(); //Team Client here can directly invoke the delegate!
如上面代码所示,在开发端不知情的情况 下,客户端能直接调用委托。在调用委托前,首先要执行其它的验证,因此,对于函数方法和变量的封装性来说不是一种好的方式。
代码审查
我们再审查一下代码,在调用委托“MyLogging”前,首先在最终地调用委托前有验证业务逻辑。
1 private void ExecuteValidation() 2 { 3 //Execution of validation and logic here 4 //With some business rules etc. 5 6 if (MyLogging != null) 7 { 8 MyLogging.Invoke(); 9 } 10 }
怎么解决?对,事件
开发端通过添加event关键词就可以解决问题:
1 //public YourLoggingHere MyLogging; 2 public event YourLoggingHere MyLogging;
这样,客户就不能直接调用委托了。如果直接调用,就如下面所示那样触发错误信息:
1 why.MyLogging.Invoke(); 2 3 //The event 'WhyUseEvents.MyLogging' can only appear on the left hand side of += or -= (except when used from within the type 'WhyUseEvents')
这就简单地解释了虽然我们可以一直使用委托却选择事件的原因:
1、可以提供封装性,不会暴露业务逻辑;
2、防止客户端清除掉所有注册到委托上的函数方法(在事件中这样做不到);
why.MyLogging = null;
3、当然了,第三点就是阻止调用委托。