匿名方法的作用与缺点

开发 后端
本文总结了匿名方法的作用:为了保留回调函数的上下文而创建一些类,对于C#程序员来说,的确是一件有些不可思议的事情。

匿名方法的作用

千万不要小看匿名方法的作用,有些时候您认为它的作用仅限于上文描述,只是因为没有在某些问题上踏前一步。例如,对于那些只需要“按需创建”,且要“线程安全”的对象,您会怎么做呢?没错,可以使用Double Check:

  1. private object m_mutex = new object();  
  2. private bool m_initialized = false;  
  3. private BigInstance m_instance = null;  
  4.  
  5. public BigInstance Instance  
  6. {  
  7.     get 
  8.     {  
  9.         if (!this.m_initialized)  
  10.         {  
  11.             lock (this.m_mutex)  
  12.             {  
  13.                 if (!this.m_initialized)  
  14.                 {  
  15.                     this.m_instance = new BigInstance();  
  16.                     this.m_initialized = true;  
  17.                 }  
  18.             }  
  19.         }  
  20.  
  21.         return this.m_instance;  
  22.     }  
  23. }  
  24.  

嗯,做的很漂亮!那么……这样的属性再来一个,再来三个,再来五个呢?可能有些朋友就会开始大段地Copy & Paste,于是错误便难免了。这里有一件真人真事,以前某位同学在一堆这样的代码中迷茫了,说为什么用了这种方法,还是初始化了多次对象了?检查了半天没有看出问题来。***发现,原因是访问了错误的initialized变量(例如,在某个应该访问artistInitialized的地方访问了articleInitialized)。可惜,大段时间已经被浪费了——更糟的是,心情也随之变差了。

其实,Copy & Paste很明显没有遵守DRY原则埃为什么不把它们封装在一处呢?例如:

  1. public class Lazy<T>  
  2. {  
  3.     public Lazy(Func<T> func)  
  4.     {  
  5.         this.m_initialized = false;  
  6.         this.m_func = func;  
  7.         this.m_mutex = new object();  
  8.     }  
  9.  
  10.     private Func<T> m_func;  
  11.  
  12.     private bool m_initialized;  
  13.     private object m_mutex;  
  14.     private T m_value;  
  15.  
  16.     public T Value  
  17.     {  
  18.         get 
  19.         {  
  20.             if (!this.m_initialized)  
  21.             {  
  22.                 lock (this.m_mutex)  
  23.                 {  
  24.                     if (!this.m_initialized)  
  25.                     {  
  26.                         this.m_value = this.m_func();  
  27.                         this.m_func = null;  
  28.                         this.m_initialized = true;  
  29.                     }  
  30.                 }  
  31.             }  
  32.  
  33.             return this.m_value;  
  34.         }  
  35.     }  
  36. }  
  37.  

于是,之前的代码就可以简化成这样了:

  1. private Lazy<BigInstance> m_lazyInstance =  
  2.     new Lazy<BigInstance>(delegate { return new BigInstance(); });  
  3.  
  4. public BigInstance Instance { get { return this.m_lazyInstance.Value; } }  
  5.  

还是太丑,上Lambda表达式!

  1. private Lazy<BigInstance> m_lazyInstance =  
  2.     new Lazy<BigInstance>(() => new BigInstance());  
  3. public BigInstance Instance { get { return this.m_lazyInstance.Value; } }  

如果没有匿名方法,许多容易使用的编程模型和方式都难以开展。例如,我们就不会有CacheHelper,也不会有AsyncTaskDispatcher(上,下),也很难利用“延迟”所带来的便利,更难以出现微软并行扩展、CCR等优秀框架。可以这么说,如果您不善于使用委托,您如果不知道如何合适地使用匿名方法,您在不自知的情况下可能就已经编写了大量额外的代码了。

老赵平时的工作之一,便是为项目提供各种扩展API,可以让程序员们更愉快地进行开发工作,得到更好的生产力,让代码变得更加美好。如今C#有了匿名方法、Lambda表达式、表达式树、扩展方法等优秀的语言特性,真让我有“如鱼得水”的感觉。因此,我对于Java这样不思进取的语言可以说深恶痛绝(Java朋友们赶快学习Scala吧)。在看阅读大量Java开源项目代码时,我常有这样的感觉:“如果是C#的话,利用匿名方法,这个类不就可以不写,那个类就可以省略……”。没错,所以匿名方法的作用就是,为了保留回调函数的上下文而创建一些类,对于C#程序员来说,的确是一件有些不可思议的事情。

至于Lambda表达式以及其他话题,我们下次再说吧。

匿名方法的缺点

匿名方法的优势在于自动形成闭包,而它的缺点也是让程序员“不自觉”地创建了闭包,这会让某些对象的生命周期加长。例如在一开始的TestRequest方法中,表面上看起来url是参数,request是局部变量,有些朋友可能会认为它们在方法退出后就已经准备回收了。不过因为形成了闭包,url和request已经“升级”为一个对象的域变量,它的生命周期延长了,延长至回调函数执行完毕。因此,一不注意可能就会产生一些莫名其妙的情况。

其实,这些都是“延迟”所带来的陷阱,作为一个优秀的开发人员,除了知道某个东西的作用和优势,也要知道它的问题,不是吗?

【编辑推荐】

  1. 概述C# 匿名函数
  2. C#在应用程序间发送消息实现浅析
  3. 一些C#时间类型的入门知识
  4. 警惕.NET中的匿名方法造成变量共享
  5. 如何使用匿名函数
责任编辑:yangsai 来源: 老赵点滴
相关推荐

2023-10-17 11:34:42

2009-08-20 16:28:45

C#匿名方法

2009-08-20 16:15:19

C# 匿名方法

2009-08-27 17:51:34

C#匿名方法

2009-06-19 18:36:15

JPAHibernate

2009-08-20 16:25:59

C# 匿名方法

2013-11-13 14:11:43

2009-03-13 10:12:18

变量共享匿名方法.NET

2009-08-21 18:01:32

C#匿名方法

2009-08-27 17:47:18

C#匿名方法作为参数传

2018-10-24 09:00:26

KafkaSpark数据

2011-05-23 11:22:37

2009-07-08 15:01:00

Servlet的作用

2010-08-03 11:35:19

Flex全屏

2012-05-03 09:58:19

VLANVLAN划分

2010-01-05 15:43:13

.NET Framew

2019-04-16 13:12:52

2012-04-02 14:03:08

web缓存

2010-07-12 14:29:42

BOOTPBOOTP协议

2010-06-30 15:57:23

匿名FTP
点赞
收藏

51CTO技术栈公众号