LINQ Enumerable

System.Linq.Enumerable类,提供了数十种称为扩展方法的共享方法,帮助您操做全部实现IEnumerable(of T)接口的类中的数据。因为Enumerable类的扩展方法能够处理许多其余类如(包括Array和List),所以不只可使用Enumerable类的方法来建立LINQ查询,还能够用它来操做数组和其余数据结构的行为。数组

查看Enumerable类扩展方法的文档,你会发现每一个成员都为Shared。所以能够经过两种方案来调用方法。数据结构

第一种方案:按照声明类型的方法来调用,即传入扩展类的实例dom

 Dim itemcount = Enumerable.Count(query, Function(prod) prod.Equals("Chang"))
函数

第二种方案:想操做集合自己的实例方法同样,调用扩展方法,没必要提供第一个参数spa

 Dim itemCount1 = queryAgain.Count(Function(qS) qS.Equals("Chang"))

从通过排序的数据中取得前10项,扩展方法Take:从序列的开头返回指定数量的连续元素。code

    Dim query = _
        db.Products.Where(Function(product) product.CategoryId = 1) _
                   .OrderBy(Function(product) product.ProductName) _
                   .Select(Function(product) product.ProductName) _
                   .Take(10)

建立序列

Enumerable类提供了多个shared方法,但他们不是扩展方法,咱们先从这些简单的方法开始。orm

Enumerable.Range

Enumerable.Range方法建立一个新的整数有序列表。可指定列表的起始值和项目数。此方法将返回一个IEnumerable(of Integer)序列。下面代码,使用Range方法填充列表,而后使用一个简单的lambda表达式调用Enumerable.orderby方法,按随机顺序排列序列。对象

        Dim rad As New System.Random
        Dim items = Enumerable.Range(1, 10)
        Dim randomList = items.OrderBy(Function() rad.Next())

屡次运行代码时,每次返回不一样的结果。排序

Enumberable.Reverse

Enumberable.Reverse方法以相反顺序返回输入序列。索引

        Dim items = Enumerable.Range(1, 10)
        Dim reversed = items.Reverse()

Enumerable.Repeat

Enumerable.Repeat方法建立包括指定值,且按指定次数重复的一个列表。

        Dim repeated = Enumerable.Repeat("Hello", 6)

执行代码后,repeated变量为

Hello, Hello, Hello, Hello, Hello, Hello
 

选择序列

Enumerable.select

Enumerable.select方法将每一个元素投影成新的格式。

 Dim db As New SimpleDataContext
 Dim results = db.Customers.Where(Function(customer) customer.Country = "USA") _
                 .Select(Function(customer, index) _
                 String.Format("{0}.{1}", index + 1, customer.ContactName))

Enumerable.selectMany

Enumerable.selectMany方法获取一个项目集合,其中的每一个项目可能又是一个项目集合,而后将两维输入缩成一维输出序列。例如,若是须要获取种类列表,每一个种类又包括多个产品,并最终获得具备对应种类信息的产品列表,此方法会很是有用。

Dim db As New SimpleDataContext
Dim categories = db.Categories _
                   .Where(Function(category) category.Products.Count < 7)

Dim reuslts = categories.SelectMany( _
    Function(category, index) category.Products.Select( _
        Function(product) String.Format("{0}.Category {1}:{2}", _
                          index, product.CategoryId, product.ProductName)))

在此示例中,传到selectMany方法的lambda表达式接受对特定种类的引用(依次处理每一个种类)。selectMany方法的这一特定重载将种类的索引以及种类一块儿传递给 lambda 表达式。有了种类及其索引后,lambda 表达式将针对种类的 Products 属性调用 Select 方法,容许它处理种类中的每一个产品。此示例返回包含如下字符串列表的一个序列。调用 SelectMany 将原始种类/产品层次结构平铺成单个值列表。

检索单个元素

你经常会须要检索和处理序列中的单个元素。Enumerable类提供了多种方法来将序列内容筛选成单个元素。

Enumerable.First、Enumerable.Last

Enumerable.first和Enumerable.last方法分别返回序列中的第一个和最后一个元素。

Enumerable.Single

给定指定单个元素的函数或者Lambda表达式后,Enumerable.Single方法将返回一个元素。

Enumerable.ElementAt

Enumerable.ElementAt方法将返回位于序列中特定索引位置的一个元素。

若是序列中并不存在请求的元素(对于Single方法而言,若是限制条件致使出现零个元素或多个元素),上述每种方法都会抛出异常。它们还容许指定一个lambda表达式或函数来限制输入数据。在任何状况下,结果序列必须包含一个元素。

Enumerable 类还提供相似方法,它在条件容许时返回单个元素,不然返回序列类型的默认成员。这些方法是 Enumerable.FirstOrDefault、Enumerable.LastOrDefault、Enumerable.SingleOrDefault 和 Enumerable.ElementAtOrDefault。

筛选序列

Enumerable.where、Enumerable.Distinct或者Enumerable.OfType方法筛选现有序列的内容,便可返回输出序列中原始数据的子集。

Enumerable.OfType

Enumerable.OfType方法基于指定类型筛选输入序列。假设但愿仅针对窗体上特定类型的控件执行操做。经过使用OfType方法,能够限制窗体公开的控件集合并仅遍历相关的控件子集。

 Dim items As New List(Of Object)
 items.Add("January")
 items.Add(0)
 items.Add("Monday")
 items.Add(3)
 items.Add(5)
 items.Add("September")

 Dim numbers = items.OfType(Of Integer)()
 Dim strings = items.OfType(Of String)()

代码运行后的,两个输出列表,包含如下数据:

0, 3, 5
January, Monday, September

Enumerable.Where

Enumerable.where方法容许指定筛选输入序列的条件。第二个重载版本可访问集合中每一个项目的索引,以便根据索引执行筛选。

Dim files As IEnumerable(Of FileInfo) = _
    New DirectoryInfo("C:\Windows").GetFiles()
Dim fileResults = _
    files.Where(Function(file) file.Length < 100) _
    .Select(Function(file) String.Format("{0}  ({1})", file.Name,file.Length))

上面代码中,New DirectoryInfo("C:\Windows").GetFiles()返回的是,System.IO.FileInfo 类型数组。因为数组实现了IEnumerable接口,所以可以使用where方法筛选数组内容。

fileResults = _
   files.Where(Function(file, index) ((file.Length < 100) And (index < 20))) _
   .Select(Function(file) String.Format("{0} ({1})", file.Name, file.Length))

Enumerable.Distinct

Enmerable.Distinct方法可筛选列表,使输出序列仅包含输入列表中单独存在的项目。对应简单的值(字符串、数字等),此过程很是简单。

对于复杂对象列表,运行时引擎如何才能经过比较肯定两个对象是否重复?没法简单地比较实例变量,这一点与在实际操做中仅比较对象的地址不一样。对于复杂对象,必须提供一个比较器,即实现IEqualityComparer(Of T)执行比较。