From Expressions (LINQ)
This includes ways to filter, sort, group and join sets of data.
from expression (also referred to as a LINQ expression, short for "Language INtegrated Query") always starts with the keyword
from, and its result is a new Sequence of the same or a derived (and possibly anonymous) type.
var lNames := from p in People where p.Age ≥ 18 select p.Name;
The beginning of the expression is formed by the two keywords
in. Much like a
for i in, the
in keyword is followed by the sequence to be iterated, and preceded by a new variable that is introduced for the iteration. This variable is available throughout the rest of the expression to refer to an individual item in the sequence.
Following the preamble can be one or more query sub-expressions, such as the
select expressions in the example above. When the LINQ expression is later executed, each sub expression is applies to the result of its predecessor.
In the above example
from p in People is the origfinal sequence of all items in the
where p.Age > 18 executes over each of these items, returning a new sequence that contains only those matching the condition (
p.Age ≥ 18).
select p.Name then runs over that sequence, i.e. only the persons age 18 or above, and it will return a new sequence that has each adult's name, instead of the full data.
As a result,
lNames will be a
sequence of String, containing the name value from all people whose age value was 18 or above.
LINQ Query Operators
The following query operators, or sub-expressions, are supported:
where can be used to filter a sequence. The expression should return a boolean where
true indicates this value will be included in the result.
var lTallPeople := from p in People where p.Height > 200;
from can also be used as a sub-expression, to introduce a sub-sequence into scope. Both the original identifier and the new variable are available in scope, afterwards:
var lChapters := from book in Books from chapter in book.Chapters where book.Author = "Stephen King" and chapter.length > 50 select Book.Title+", Chapter "+Chapter.Title; // all chapters by Stephe King that are longer than 50 pages
with can be used to evaluate a sub-expression, store it, and give it a name, so it can be reused in additional queries.
var s := "A sentence"; var vowels := from letter in s with lower := Char.ToLower(letter) where lower in ['e', 'u', 'i', 'o', 'a']
join expressions can join two seperate collections together. An optional
into clause can change the name of the resulting identifier.
var lBooksWithAuthor := from b in Books join a in Authors on b.Author equals author.ID select new class (Book := b, Author = a);
order by (descending)
order by is used to sort a sequence in a specific order. It expects an expression that is comparable. To sort by multiple criteria, more than one exprerssion can be provided, separated with a comma. An optional
ascecnding (default) or
descecnding modifier can be appended after each expression to reverse the order.
var lSorted := from p in People order by p.Name ascending, p.Age descending select p.Name+", age "+p.Age;
select can be used to convert each item of the sequence to a derived value, which can be of the same or a different type. When
select is not the final query operator in the expression, the
into keyword has to be used to provide a new identifier for the rest of the expression.
var lShortPasswords := from u in Users where not u.Disabled select u.Password into p where p.Length < 8;
group by is used to partition a sequence into sub-groups by an expression.
The result returns a grouped sequence with one entry for each group, which contains both the shared value, as well as all items of the subgroup as nested sequence.
When this is not the final query operator in the expression, the
into keyword has to be used to provide a new identifier for the rest of the expression. The identifier after group is implied to be the current LINQ query identifier, if it's omitted.
var lPeopleByAge = from p in People group s by s.Age;
As the name implies,
reverse reverses the order in which things are returned.
var x := [1,2,3,4,5]; var y := from a in x reverse; // 5,4,3,2,1
distinct filters out duplicates items in a sequence, so that each unique value is only contained once in the result.
var x := [1,2,3,2,4,4,5]; var y := from a in x distinct; // 1,2,3,4,5
take takes a limited number of elements from the collection and stops returning after that.
var x := [1,2,3,4,5,6,7]; var y := from a in x take 5; // 1,2,3,4,5
take while returns items as long as the provided expression returns true.
var x := [1,2,3,4,5,4,3,2,1,0]; var y := from a in x take while a < 4; // 1,2,3
skip skips a number of elements before returning from the collection. If the end of the collection is reached before the appropriate number of items where skipped, the resulting sequence will be empty.
var x := [1,2,3,4,5,6,7]; var y := from a in x skip 3; // 4,5,6,7
skip while skips items as long as the expression returns true.
var x := [1,2,3,4,5,4,3,2,1]; var y := from a in x skip while a < 4 select a; // 4,5,4,3,2,1