在泛型列表方法中使用Lambda表达式作为Predicate, Func和Action参数
参见原文链接
##简介
自从.NET泛型出现后,我在工作的项目中用泛型列表完成了很多的工作,它们是对对象进行存储,检索和其他一般操作的非常好的方式。泛型列表类的大多数方法将Predicate,Func,或者Action作为其参数。一开始这会让人有点疑惑。这篇文章旨在消除疑惑并让你通过在这三种类型参数中使用lambda表达式让你的代码更加的优雅。
如果你是lambda表达式新手,请看微软的这篇文章:
http://msdn.microsoft.com/en-us/library/bb397687.aspx
这是本文介绍的三种类型的简单定义:
Predicate
一种委托,带参数,并且参数在代码块中被使用,永远返回布尔类型Func
一种委托,带参数,并且参数在代码块中被使用,返回类型可以自定义Action
一种委托,带参数,并且参数在代码块中被使用,无返回值
对于泛型列表,这些参数可以使程序员对列表中的每个元素执行一个方法。
##Common Code
本文的所有例子使用同一份的公共代码,以下是业务实体:
这是使用的列表成员变量。
这是列表中存储的内容:
##带Predicate参数的列表方法
泛型列表类的Find
方法是一个使用Predicate作为参数的例子。为了创建一个Predicate类,让我们先看看一个典型的查找是如何完成的。对于我而言,foreach
方法是我最好的朋友,无论我是使用泛型列表,ArrayList或是其他任何数据结构。例子如下:
现在,有一个更好的方式来完成这个一般性工作。泛型列表类通过一个内置的Find
方法来实现它。传给Find
方法的参数是泛型类。还记得Predicate的简单定义吧:“一种委托,带参数,并且参数在代码块中被使用,永远返回布尔类型”。在C#中,一个内联的委托创建一个匿名方法,这可以被赋值给Predicate变量。Predicate变量然后就可以像下面这样传给Find
方法:
如果你想保存委托并重用,这非常有用。当然委托也可以简单地传给Find
方法,如下:
正则表达式简化了上述代码。这是一个使用lambda表达式的Predicate的例子,在“=”右边是lambda表达式。
正则表达式可以读作“符合其ID == inventoryID的元素”。换句话说,元素是”=>”右边的参数。Predicate变量仍然可以重用。在我看来,使用lambda表达式看起来更整洁。进一步简化,Predicate变量支持以lambda表达式的形式直接传给Find
方法,如下:
The preceding Find examples all output the same with an inventoryID of 5 as shown:
下述带Predicate参数的泛型列表方法也很有用:
FindAll
- 返回符合条件的对象列表RemoveAll
- 移除符合条件的对象Exists
- 是否存在符合条件的对象存在?FindLast
- 返回符合条件的最末一个对象
完整列表请参见 http://msdn.microsoft.com/en-us/library/s6hkc2c4.aspx
##带Func参数的列表方法 有许多列表方法带Func类型参数。还记得Func的简单定义吧:“一种委托,带参数,并且参数在代码块中被使用,返回类型可以自定义”。Func比Predicate更灵活,因为它可以返回任何类型,而不仅仅是布尔值。有些Func带一个参数,有些带多个,取决于列表方法。
一个更有用的List方法叫Where
,实际上是Enumerable的扩展方法。考虑一下使用此方法的SQL WHERE子句。它允许你得到一个Where Func指定的列表子集。下面是使用delegate的例子:
既然这里要返回一个InventoryItem的列表,你必须调用ToList
因为Where返回一个IEnumerable,直到结果被枚举时查询才会执行。
上述例子能用Lambda表达式进行简化:
同样,这里的写法主要是在其他代码中重用Func。最好的简化是简单的直接向Where
方法传递一个lambda表达式,如下:
上述Where的例子输出相同的unitCost为2.0的值。
下面的泛型列表方法有Func参数,也很有用:
FirstOrDefault
- 返回满足条件的第一个元素,或者返回一个默认值(对于对象,默认值为null)LastOrDefault
- 返回满足条件的最末一个元素,或者返回一个默认值(对于对象,默认值为null)First
- 返回满足条件的第一个元素
完整列表参见: http://msdn.microsoft.com/en-us/library/s6hkc2c4.aspx
##带Action参数的列表方法
还记得Action的简单定义吧:“一种委托,带参数,并且参数在代码块中被使用,无返回值”。泛型列表类中有一个方法ForEach
带Action参数。作用是对列表中的每一个元素执行你指定的代码。
在下面的例子中,对每一个inventory元素unit cost被设置成相同的值(单独的Action变量也可以通过委托或lambda表达式创建,然后传给ForEach
方法):
输出下面的结果:
当然我也可以用ForEach
命令输出结果:
##结论
泛型列表类及其扩展有一些非常强大的方法,可以帮助你干一般性的工作。其中许多带Predicate,Func或者Action参数。最 简洁优雅的使用方法是向这类方法传递lambda表达式,LINQ非常重要的一部分。
blog comments powered by Disqus