Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharpNotesForProfessionals.pdf
Скачиваний:
57
Добавлен:
20.05.2023
Размер:
6.12 Mб
Скачать

Chapter 66: LINQ Queries

LINQ is an acronym which stands for Language INtegrated Query. It is a concept which integrates a query language by o ering a consistent model for working with data across various kinds of data sources and formats; you use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET Datasets,

.NET collections, and any other format for which a LINQ provider is available.

Section 66.1: Chaining methods

Many LINQ functions both operate on an IEnumerable<TSource> and also return an IEnumerable<TResult>. The type parameters TSource and TResult may or may not refer to the same type, depending on the method in question and any functions passed to it.

A few examples of this are

public static IEnumerable<TResult> Select<TSource, TResult>( this IEnumerable<TSource> source,

Func<TSource, TResult> selector

)

public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, int, bool> predicate

)

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>( this IEnumerable<TSource> source,

Func<TSource, TKey> keySelector

)

While some method chaining may require an entire set to be worked prior to moving on, LINQ takes advantage of deferred execution by using yield return MSDN which creates an Enumerable and an Enumerator behind the scenes. The process of chaining in LINQ is essentially building an enumerable (iterator) for the original set -- which is deferred -- until materialized by enumerating the enumerable.

This allows these functions to be fluently chained wiki, where one function can act directly on the result of another. This style of code can be used to perform many sequence based operations in a single statement.

For example, it's possible to combine SELECT, Where and OrderBy to transform, filter and sort a sequence in a single statement.

var

someNumbers

=

{

4,

3, 2, 1 };

var

processed =

someNumbers

 

 

 

.Select(n

=> n

*

2)

// Multiply each number by 2

 

.Where(n =>

n

!=

6)

//

Keep all the results, except for 6

 

.OrderBy(n =>

n);

//

Sort in ascending order

 

 

 

 

 

 

 

 

 

Output:

2

4

8

GoalKicker.com – C# Notes for Professionals

348

Live Demo on .NET Fiddle

Any functions that both extend and return the generic IEnumerable<T> type can be used as chained clauses in a single statement. This style of fluent programming is powerful, and should be considered when creating your own extension methods.

Section 66.2: First, FirstOrDefault, Last, LastOrDefault, Single,

and SingleOrDefault

All six methods return a single value of the sequence type, and can be called with or without a predicate.

Depending on the number of elements that match the predicate or, if no predicate is supplied, the number of elements in the source sequence, they behave as follows:

First()

Returns the first element of a sequence, or the first element matching the provided predicate.

If the sequence contains no elements, an InvalidOperationException is thrown with the message: "Sequence contains no elements".

If the sequence contains no elements matching the provided predicate, an InvalidOperationException is thrown with the message "Sequence contains no matching element".

Example

// Returns "a":

new[] { "a" }.First();

// Returns "a":

new[] { "a", "b" }.First();

// Returns "b":

new[] { "a", "b" }.First(x => x.Equals("b"));

// Returns "ba":

new[] { "ba", "be" }.First(x => x.Contains("b"));

// Throws InvalidOperationException:

new[] { "ca", "ce" }.First(x => x.Contains("b"));

// Throws InvalidOperationException: new string[0].First();

Live Demo on .NET Fiddle

FirstOrDefault()

Returns the first element of a sequence, or the first element matching the provided predicate.

If the sequence contains no elements, or no elements matching the provided predicate, returns the default value of the sequence type using default(T).

Example

// Returns "a":

new[] { "a" }.FirstOrDefault();

// Returns "a":

new[] { "a", "b" }.FirstOrDefault();

GoalKicker.com – C# Notes for Professionals

349

// Returns "b":

new[] { "a", "b" }.FirstOrDefault(x => x.Equals("b"));

// Returns "ba":

new[] { "ba", "be" }.FirstOrDefault(x => x.Contains("b"));

// Returns null:

new[] { "ca", "ce" }.FirstOrDefault(x => x.Contains("b"));

// Returns null:

new string[0].FirstOrDefault();

Live Demo on .NET Fiddle

Last()

Returns the last element of a sequence, or the last element matching the provided predicate.

If the sequence contains no elements, an InvalidOperationException is thrown with the message "Sequence contains no elements."

If the sequence contains no elements matching the provided predicate, an InvalidOperationException is thrown with the message "Sequence contains no matching element".

Example

// Returns "a":

new[] { "a" }.Last();

// Returns "b":

new[] { "a", "b" }.Last();

// Returns "a":

new[] { "a", "b" }.Last(x => x.Equals("a"));

// Returns "be":

new[] { "ba", "be" }.Last(x => x.Contains("b"));

// Throws InvalidOperationException:

new[] { "ca", "ce" }.Last(x => x.Contains("b"));

// Throws InvalidOperationException: new string[0].Last();

LastOrDefault()

Returns the last element of a sequence, or the last element matching the provided predicate.

If the sequence contains no elements, or no elements matching the provided predicate, returns the default value of the sequence type using default(T).

Example

// Returns "a":

new[] { "a" }.LastOrDefault();

// Returns "b":

new[] { "a", "b" }.LastOrDefault();

// Returns "a":

new[] { "a", "b" }.LastOrDefault(x => x.Equals("a"));

// Returns "be":

GoalKicker.com – C# Notes for Professionals

350

new[] { "ba", "be" }.LastOrDefault(x => x.Contains("b"));

// Returns null:

new[] { "ca", "ce" }.LastOrDefault(x => x.Contains("b"));

// Returns null:

new string[0].LastOrDefault();

Single()

If the sequence contains exactly one element, or exactly one element matching the provided predicate, that element is returned.

If the sequence contains no elements, or no elements matching the provided predicate, an InvalidOperationException is thrown with the message "Sequence contains no elements".

If the sequence contains more than one element, or more than one element matching the provided predicate, an InvalidOperationException is thrown with the message "Sequence contains more than one element".

Note: in order to evaluate whether the sequence contains exactly one element, at most two elements has to be enumerated.

Example

// Returns "a":

new[] { "a" }.Single();

//Throws InvalidOperationException because sequence contains more than one element: new[] { "a", "b" }.Single();

//Returns "b":

new[] { "a", "b" }.Single(x => x.Equals("b"));

// Throws InvalidOperationException:

new[] { "a", "b" }.Single(x => x.Equals("c"));

//Throws InvalidOperationException: new string[0].Single();

//Throws InvalidOperationException because sequence contains more than one element: new[] { "a", "a" }.Single();

SingleOrDefault()

If the sequence contains exactly one element, or exactly one element matching the provided predicate, that element is returned.

If the sequence contains no elements, or no elements matching the provided predicate, default(T) is returned.

If the sequence contains more than one element, or more than one element matching the provided predicate, an InvalidOperationException is thrown with the message "Sequence contains more than one element".

If the sequence contains no elements matching the provided predicate, returns the default value of the sequence type using default(T).

Note: in order to evaluate whether the sequence contains exactly one element, at most two elements has to be enumerated.

Example

// Returns "a":

new[] { "a" }.SingleOrDefault();

GoalKicker.com – C# Notes for Professionals

351