技术开发 频道

C#2.0函数式编程

 封装逻辑

 既然没有“扩展方法”,我们要避免静态方法的调用形式,那么就只能在一个类中定义逻辑了。这点并不困难,毕竟在API的设计发展至今,已经进入了关注FluentInterface的阶段,这方面已经积累了大量的实践。于是我们构造一个Enumerable< T>类,封装IEnumerable< T>对象,以此作为扩展的入口:

 publicclassEnumerable< T>

 {

 privateIEnumerable< T>m_source;

 publicEnumerable(IEnumerable< T>source)

 {

 if(source==null)thrownewArgumentNullException("source");

 this.m_source=source;

 }

 ...

 }

 并以此定义所需的Select和Where方法:

 publicEnumerable< T>Where(Func< T,bool>predicate)

 {

 if(predicate==null)thrownewArgumentNullException("predicate");

 returnnewEnumerable< T>(Where(this.m_source,predicate));

 }

 privatestaticIEnumerable< T>Where(IEnumerable< T>source,Func< T,bool>predicate)

 {

 foreach(Titeminsource)

 {

 if(predicate(item))

 {

 yieldreturnitem;

 }

 }

 }

 publicEnumerable< TResult>Select< TResult>(Func< T,TResult>selector)

 {

 if(selector==null)thrownewArgumentNullException("selector");

 returnnewEnumerable< TResult>(Select(this.m_source,selector));

 }

 privatestaticIEnumerable< TResult>Select< TResult>(IEnumerable< T>source,Func< T,TResult>selector)

 {

 foreach(Titeminsource)

 {

 yieldreturnselector(item);

 }

 }

 这些扩展都是些高阶函数,也都有延迟效果,相信很容易理解,在此就不多作解释了。在这里我们直接观察其使用方式:

 List< int>even=newEnumerable< string>(strArray)

 .Select(delegate(strings){returnInt32.Parse(s);})

 .Where(delegate(inti){returni%2==0;})

 .ToList();

 不知道您对此有何感觉?

 老赵对此并不满意,尤其是和C#3.0相较之下。我们虽然定义了Enumerable封装类,并提供了Select和Where等逻辑,但是由于匿名函数的构造还是较为丑陋。使用delegate构造匿名函数还是引起了不少噪音:

 与JavaScript的function关键字,和VB.NET的Function关键字一样,C#2.0在构造匿名函数时无法省确delegate关键字。

 与C#3.0中的Lambda表达式相比,使用delegate匿名函数缺少了必要的类型推演。

 使用delegate构造匿名函数时必须提供完整的方法体,也就是只能提供“语句”,而不能仅为一个“表达式”,因此return和最后的分号无法省确。

 我们设法拯救C#2.0,但是我们真的做到了吗?

 框架/类库真能弥补语言的生产力吗?

查看原文地址

0
相关文章