Класс Enumerable LINQ - Извлечение отдельного элемента

ОГЛАВЛЕНИЕ

Извлечение отдельного элемента

Зачастую требуется извлечь из последовательности единственный элемент и поработать с ним. Класс Enumerable предоставляет несколько методов, позволяющих отфильтровать содержимое последовательности до одного элемента. Методы Enumerable.First и Enumerable.Last возвращают соответственно первый или последний элемент последовательности. Метод Enumerable.Single возвращает элемент при наличии функции или лямбда-выражения, указывающего единственный элемент. Метод Enumerable.ElementAt возвращает из последовательности один элемент, обладающий конкретным индексом.

Все эти методы создают исключение, если в последовательности нет запрошенного элемента, или, в случае метода Single, если ограничения приводят либо к нулевому числу элементов, либо к нескольким элементам. Каждый из этих методов позволяет также указывать лямбда-выражение или функцию для ограничения входных данных. В любом случае результирующая последовательность должна содержать единственный элемент.

Класс Enumerable также предоставляет подобные методы, возвращающие единственный элемент, если это возможно, а если невозможно – член по умолчанию с типом, свойственным последовательности. К числу этих методов принадлежат Enumerable.FirstOrDefault, Enumerable.LastOrDefault, Enumerable.SingleOrDefault и Enumerable.ElementAtOrDefault. На рис. 2 показано поведение этих методов. Выполнение примера приводит к помещению следующих данных в выходной поток.

ALFKI: Maria Anders
ALFKI: Maria Anders
Last in USA: Karl Jablonski
Sequence contains no elements
Specified argument was out of the range of valid values.
Parameter name: index
CustomerID = XXXXX is Nothing: True
Customer 2 in USA is Nothing: False
Customer 200 in USA is Nothing: True

Рис. 2 Извлечение элементов с помощью методов класса Enumerable

' From SingleElementDemo in the sample:

Dim oneCustomer As Customer
Dim sw As New StringWriter

Dim db As New SimpleDataContext

Dim query0 = From cust In db.Customers

Dim query1 = _
  From cust In db.Customers _
  Where cust.CustomerID = "ALFKI"

Dim query2 = _
  From cust In db.Customers _
  Where cust.Country = "USA"

Dim query3 = _
  From cust In db.Customers _
  Where cust.CustomerID = "XXXXX"

' This works fine, finds the customer whose CustomerID is ALFKI:
oneCustomer = query1.Single
sw.WriteLine("ALFKI: {0}", oneCustomer.ContactName)

' You can supply an expression to filter, when calling 
' the First, Last, Single, and so on, methods:
oneCustomer = query0.Single( _
  Function(cust) cust.CustomerID = "ALFKI")
sw.WriteLine("ALFKI: {0}", oneCustomer.ContactName)

' This works fine, finds the last customer in the USA:
oneCustomer = query2.Last
sw.WriteLine("Last in USA: {0}", oneCustomer.ContactName)

' These two raise exceptions:
Try
  ' There's no customer use customer ID is "XXXXX":
  oneCustomer = query3.Single
Catch ex As Exception
  sw.WriteLine(ex.Message)
End Try

Try
  ' There aren't 200 customers in the USA:
  oneCustomer = query2.ElementAt(200)
Catch ex As Exception
  sw.WriteLine(ex.Message)
End Try

' These don't raise exceptions, but return default values
' if they fail:
oneCustomer = query3.SingleOrDefault
sw.WriteLine("CustomerID = XXXXX is Nothing: {0}", _
  oneCustomer Is Nothing)

' Because there are at least two customers in the USA,
' method returns a valid, single customer:
oneCustomer = query2.ElementAtOrDefault(2)
sw.WriteLine("Customer 2 in USA is Nothing: {0}", _
  oneCustomer Is Nothing)

oneCustomer = query2.ElementAtOrDefault(200)
sw.WriteLine("Customer 200 in USA is Nothing: {0}", _
  oneCustomer Is Nothing)