VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > VB.net教程 >
  • C#入门lambda表达式

本次的内容,主要是针对已经学习过C# 2.0的程序员读者的,前提是已经知道什么是匿名方法。如果还不清楚,请先阅读“连载:C# 2.0入门”(这篇会在今后翻译)。

  好的,现在进入正题。

  Lambda表达式(λ表达式),用一句话来解释,(不算很严谨)就是使匿名方法文字上更短的语法。虽然这样说,单“仅仅是文字上的变化,源代码的性质没有变”这样的想法也是一种误解。规模变化了,其性质也会变化。例如,实验室的烧杯中产生的现象,不一定会在大型的工厂里产生。同样的道理也适用于源代码。

  那么,就体验一下Lambda表达式吧。

  以下,使用具体的code来说明一下,不是实际工程中的代码,而是实际代码使用C# 2.0重写的。

  前一阵子笔者实际写的code中,有一个菜单,能够选择的下拉菜单。菜单项是下面这样定义的:

 1public delegate bool SimpleMenuAction();
 2
 3public class  MenuItemA // 菜单项
 4{
 5  public readonly string Name; // 名字
 6  public readonly SimpleMenuAction Action; //执行内容
 7
 8  public MenuItemA(string name, SimpleMenuAction action)
 9  {
10    Name = name;
11    Action = action;
12  }
13}
14

  List 1 菜单项的定义

  与之相对应,以下是菜单项的数组。

1private static MenuItemA[] Menu Items1 =
2  {
3    new MenuItemA("选择项1", 执行方法),
4    new MenuItemA("选择项2", 执行方法),
5    new MenuItemA("选择项3", 执行方法),
6  };
7

编缉推荐阅读以下文章

  • [C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
  • [C# 3.0 入门] [第一章 Lambda表达式] 第四节:Lambda的用途 & 类型声明能够和不能够省略的情况
  • [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
  • [C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
  • C# 3.0 入门系列(一)
 

  List 2 菜单项目数组

  实际上,当时认为这样就足够了,谁知中途又被要求加入一种菜单项,这种菜单项在19点以后才可以看到。如果只有这一个的话,用if语句括起来判断一下例外条件就能够处理,可是要求是2个,而且还可能增加。于是,就想在这个表中添加条件语句。

  最simple的解决方案,应该就是在MenuItem类里,保存“几点以后有效”的“几点”的整数值。

  首先在MenuItemA类中,加上保存时间的整数字段“FromHour”。

 1public class MenuItemB
 2{
 3  public readonly string Name;
 4  public readonly SimpleMenuAction Action;
 5  public readonly int FromHour;
 6
 7  public MenuItemB(string name, SimpleMenuAction action, int fromHour)
 8  {
 9    Name = name;
10    Action = action;
11    FromHour = fromHour;
12  }
13}
14

  List 3 加上时间字段的菜单项定义

  菜单项数组也改写成以下:

1private static MenuItemB[] MenuItems2 =
2  {
3    new MenuItemB("选择项1", 执行方法, 0),
4    new MenuItemB("选择项2", 执行方法, 0),
5    new MenuItemB("选择项3", 执行方法, 0),
6    new MenuItemB("选择项4", 执行方法, 19),
7  };
8

  List 4 对List 3的菜单项进行修正

  这样,需要的信息都能够包含在数组里了。

  构建菜单的方法是,通过检查被选择的菜单对象的FromHour的值,如果与现在时间相比小,就把该菜单项显示出来。

编缉推荐阅读以下文章

  • [C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
  • [C# 3.0 入门] [第一章 Lambda表达式] 第四节:Lambda的用途 & 类型声明能够和不能够省略的情况
  • [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
  • [C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
  • C# 3.0 入门系列(一)
 

  这么看来,这个code如果按照YAGNI*的原则来看的话就比较完善了,这样的代码也属于良品了。

  * YAGNI是“You Aren't Going to Need It.”的简写,意思是:或许是必要的功能实际上并不必要的可能性非常高。一句话,为未知的未来而事先准备的代码,基本上是没用的。这样的教训很多。

  但是,这个代码来应对需求变更的要求,恐怕还太脆弱。例如,条件如果从19点改为19点半,就没法办了。或者要求设置个结束时间,或者是个时间段的话,或是根据星期几而变动,这种要求实在是太多了。

  琢磨了一下要求,加入能够指定条件的代码,修正后如下:

 1public delegate bool SimpleMenuAvailability();
 2
 3public class MenuItemC
 4{
 5  public readonly string Name;
 6  public readonly SimpleMenuAction Action;
 7  // 判断现在是否是有效菜单项
 8  public readonly SimpleMenuAvailability IsAvailable;
 9
10  public MenuItemC(string name, SimpleMenuAction action, SimpleMenuAvailability isAvailable)
11  {
12    Name = name;
13    Action = action;
14    IsAvailable = isAvailable;
15  }
16}
17

  List5 加上条件的菜单定义

  如果使用匿名方法,数组就要改写成如下:

  Menu

 1private static MenuItemC[] MenuItems3 =
 2  {
 3    new MenuItemC(
 4     "选择1", 执行方法, delegate() { return true; }),
 5    new MenuItemC(
 6     "选择2", 执行方法, delegate() { return true; }),
 7    new MenuItemC(
 8     "选择3", 执行方法, delegate() { return true; }),
 9    new MenuItemC(
10     "选择4", 执行方法, delegate() { return DateTime.Now.Hour >= 19; } ),
11  };
12

编缉推荐阅读以下文章

  • [C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
  • [C# 3.0 入门] [第一章 Lambda表达式] 第四节:Lambda的用途 & 类型声明能够和不能够省略的情况
  • [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
  • [C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
  • C# 3.0 入门系列(一)
 

  List 6 List 5中对应的菜单项

  可是,这样的代码如果要为将来可能需要也可能不需要的变化准备的话,将会变得相当臃肿。本质上完全没有意义的delegate和return显得非常刺眼,看上去很难理解意图。这种代码就是YAGNI原则所说的那种应该避免的代码的典型例子。

  因此,如果使用C# 2.0,这种code应该就不会被采用。笔者虽然属于那种对匿名方法使用得挥金如土的类型,在这个case上,(用匿名方法)恐怕优势要小于劣势。

  然而,下面这并不是匿名方法,打眼一看就是较少的文字就能描述的Lambda表达式。下面的代码,“()=>true”和“()=>DateTime.Now.Hour > 19”,一看就是Lambda表达式的样子。

1private static MenuItemC[] MenuItems4 =
2  {
3    new MenuItemC("选择项1", 执行方法, ()=>true),
4    new MenuItemC("选择项2", 执行方法, ()=>true),
5    new MenuItemC("选择项3", 执行方法, ()=>true),
6    new MenuItemC("选择项4", 执行方法, ()=>DateTime.Now.Hour >= 19),
7  };
8

  List 7 对List 6改用Lambda表达式后

  说实话,code写成这样应该可以通过了。虽然违反了YAGNI的原则,但在不损害code的可理解性的范围内,对于未知修改来说也是上了保险了。

  事实上这个保险也确实起作用。很快,菜单的有效时间从“19点以后”变成“19点后22点前”。来吧,数组做如下修正:

1private static MenuItemC[] MenuItems5 =
2  {
3    new MenuItemC("选择项1", 执行方法, ()=>true),
4    new MenuItemC("选择项2", 执行方法, ()=>true),
5    new MenuItemC("选择项3", 执行方法, ()=>true),
6    new MenuItemC("选择项4", 执行方法,
7            ()=>DateTime.Now.Hour >= 19 && DateTime.Now.Hour < 22),
8  };
9

 

  List 8 List 7中第四个菜单项的修改

  这个变更,只用改写一个Lambda表达式这样的局部变更就能搞定,一瞬间的事。但是,如果采用最初的List 4的code,菜单项类还要加上结束时间,菜单的构建方法中还要加上判断,相当的费事。然而,不仅如此,如果不是Lambda表达式,而是使用匿名方法的前提下,或许这种费事的方法也会得到采用。总之,匿名方法与Lambda表达式的长度上的差别对code会有质的影响。

 

编缉推荐阅读以下文章

  • [C# 3.0 入门] [第一章 Lambda表达式] 第五节:Lambda表达式的使用范例 & Lambda表达式的各种变体
  • [C# 3.0 入门] [第一章 Lambda表达式] 第四节:Lambda的用途 & 类型声明能够和不能够省略的情况
  • [C# 3.0 入门] [第一章 Lambda表达式] 第三节:Lambda与匿名方法的区别
  • [C# 3.0 入门] [第一章 Lambda表达式] 第一节:C# 3.0 是什么 & C# 3.0的适用范围
  • C# 3.0 入门系列(一)
 

  List 2 菜单项目数组

  实际上,当时认为这样就足够了,谁知中途又被要求加入一种菜单项,这种菜单项在19点以后才可以看到。如果只有这一个的话,用if语句括起来判断一下例外条件就能够处理,可是要求是2个,而且还可能增加。于是,就想在这个表中添加条件语句。

  最simple的解决方案,应该就是在MenuItem类里,保存“几点以后有效”的“几点”的整数值。

  首先在MenuItemA类中,加上保存时间的整数字段“FromHour”。

 1public class MenuItemB
 2{
 3  public readonly string Name;
 4  public readonly SimpleMenuAction Action;
 5  public readonly int FromHour;
 6
 7  public MenuItemB(string name, SimpleMenuAction action, int fromHour)
 8  {
 9    Name = name;
10    Action = action;
11    FromHour = fromHour;
12  }
13}
14

  List 3 加上时间字段的菜单项定义

  菜单项数组也改写成以下:

1private static MenuItemB[] MenuItems2 =
2  {
3    new MenuItemB("选择项1", 执行方法, 0),
4    new MenuItemB("选择项2", 执行方法, 0),
5    new MenuItemB("选择项3", 执行方法, 0),
6    new MenuItemB("选择项4", 执行方法, 19),
7  };
8

  List 4 对List 3的菜单项进行修正

  这样,需要的信息都能够包含在数组里了。

  构建菜单的方法是,通过检查被选择的菜单对象的FromHour的值,如果与现在时间相比小,就把该菜单项显示出来。


相关教程