另类的思维 将事件视为对象

开发 后端
我们这里将讨论一下这个另类的思维,那就是如果一个语言(平台)把事件视为对象,则表明它把“事件”作为了语言的一等公民来对待。这会不会产生错误?

将事件视为对象,有的时候就是把事件的级别进行了提升,这样就能有效地提高语言的抽象能力。有的时候会出现错误,但还是值得尝试的。

如果一个语言(平台)把事件视为对象,则表明它把“事件”作为了语言的一等公民来对待。这意味着,我们可以把一个单独的事件作为参数传递给方法,也可以将其作为一个对象的一部分,这有效地提高语言的抽象能力。试想,如果没有“委托”,在.NET中就无法把“方法”看作是对象,也就很难使用如今各种灵活的抽象方式。同样,由于.NET本身无法将事件作为单个对象处理,因此在某些时候就会束手束脚,也难以引入一些特别的编程模型。

这就是“把事件作为对象进行传递”的实际意义。

在上一篇文章里,我们提出了一种“解决方案”,它允许我们编写这样的代码:

  1. class Program  
  2. {  
  3. public event EventHandler Submit;  
  4.    
  5. static void Main(string[] args)  
  6. {  
  7. Program p = new Program();  
  8. var ev = EventFactory.Create(() => p.Submit);  
  9. ev += (sender, eventArgs) => Console.WriteLine(sender);  
  10.    
  11. p.Submit("Hello World", EventArgs.Empty);  
  12.    
  13. Console.WriteLine("Press any key to exit...");  
  14. Console.ReadLine();  
  15. }  

看上去挺那么像回事儿的,使用方式和传统的事件似乎没有太大区别。但是文末我提到这里其实有些“糊弄”的意味,而我们的装配脑袋同学、以及“脑袋装配得不输给装配脑袋”的RednaxelaFX,这两位纯爷们也都指出了问题。

信脑袋,得永生。信RednaxelaFX,原地满状态复活。

以上代码的“忽悠”,在于操作Program.Submit的代码处于Program类之内。如果我们想要使用相同的做法操作其他类的事件就做不到了,例如:

  1. public class MyClass  
  2. {  
  3. public event EventHandler MyEvent;  
  4. }  
  5.  
  6. class Program  
  7. {  
  8. static void Main(string[] args)  
  9. {  
  10. var myClass = new MyClass();  
  11. var ev = EventFactory.Create(() => myClass.MyEvent);  
  12. }  

这样的代码看似没有问题,但是编译器会提示这样的错误:

The event 'SimpleConsole.MyClass.MyEvent' can only appear on the left hand side of += or -= (except when used from within the type 'SimpleConsole.MyClass')

编译器告诉我们,除了在MyClass类的内部,MyEvent事件只能出现在+=或-=操作的左边。之前提到的两位纯爷们在前文的评论中也有过相关及衍生的讨论。因此,我们目前的做法是失败的。

前文的评论中还有朋友提到,我们事实上也可以把一个事件作为参数传递给一个方法(然后在方法里添加或删除处理程序),只要使用ref关键字就可以了,例如:

  1. static void RegisterHandlers(ref EventHandler e) { ... } 

然后:

  1. static void Main(string[] args)  
  2. {  
  3. var myClass = new MyClass();  
  4. RegisterHandlers(ref myClass.MyEvent);  

不过很显然,这样的做法也会遇到相同的问题:除非是Program内部的事件,我们不能把它像一个委托对象那样传递。而且,即使可以传递,我们也只能为它添加或删除处理函数,而不能把它作为另一个对象的一部分,然后经过各种处理之后,还可以对这个事件进行操作。

因此,我们要实现的其实是这样一个类型:

  1. public class DelegateEvent  
  2. {  
  3. ...  
  4.  
  5. public DelegateEvent AddHandler(TDelegate handler) { ... }  
  6.  
  7. public DelegateEvent RemoveHandler(TDelegate handler) { ... }  
  8. }  

这就是今天“趣味编程”的题目:将DelegateEvent<>类型实现完整,并尽可能做到严谨和易用(即适用于各种场合,各种方式进行“构造”)。

所谓“趣味编程”,是指那些我觉得难度适中的小题目,并可以锻炼“编程能力”或“语言类库的掌握程度”。一般来说它们都源自实际项目,只不过改造成“题目”时进行了“抽象”和“提炼”。个人认为它们还是挺适合作为平时的编程练习来使用的,感兴趣的朋友们不妨一试。

至于题目是否真的有“趣味”……这个见仁见智吧。我想,要让那些对于那些视编程如磨难的朋友们感到有趣,应该不比登天要容易一些。

原文标题:趣味编程:将事件视为对象

链接:http://www.cnblogs.com/JeffreyZhao/archive/2009/09/09/more-on-event-as-object.html

【编辑推荐】

  1. C#线程同步详细分析
  2. C#探讨木马程序浅谈
  3. C# Pop3Connection类简介
  4. C#数据类型简单介绍
  5. C#计算素数序列浅谈

 

责任编辑:彭凡 来源: 博客园
相关推荐

2010-06-01 09:20:45

jQuery

2016-12-21 09:57:03

大数据

2022-03-31 10:27:34

区块链黄金技术

2013-09-13 15:19:08

英特尔移动平台IDF

2010-11-19 15:39:58

2022-02-21 11:07:19

AI/ML人工智能

2021-01-18 15:28:13

加密货币比特币货币

2009-10-29 13:20:53

光纤接入网

2024-06-26 19:14:53

2023-05-23 10:30:56

CEOAI

2015-03-13 09:30:23

iOS内存管理

2016-11-04 13:52:05

物联网物联网战略

2011-07-21 17:19:47

java面向对象

2021-05-13 09:47:47

Bot攻击网络安全网络攻击

2021-05-19 10:38:18

网络安全零信任黑客

2009-06-22 13:48:00

Java编程思想面向对象

2011-04-25 13:13:02

Javafinalize

2015-09-25 10:58:20

2010-11-23 11:16:35

MySQL表别名

2009-10-23 17:10:27

试用达人
点赞
收藏

51CTO技术栈公众号