LINQ

LINQ Expressions, short for "Language INtegrated Query", provide an elegant SQL-like way to perform query operations on Sequences and collections of data.

This includes ways to filter, sort, group and join sets of data. A LINQ expression always starts with the keyword from, and its result is always a new Sequence of the same or a derived (and possibly anonymous) type.

In Oxygene, the from expression can be combined with for loops using the for each from shortcut syntax, to combine a query expression with the loop that iterates it.

Please refer to the documentation for from Expressions in Oxygene and the Standard Query Operators Overview provided by Microsoft for C#, for more details on how to use LINQ

Oxygene and C# Languages Only

This topic applies to the Oxygene and C# languages only. LINQ is not available in Swift, Java and Go as a language feature (although the Query Expressions methods can be used as regular methods, of course).

LINQ Expressions in Oxygene vs. C#

In general, Oxygene use the same syntax for LINQ queries as C#, with a few differences.

Oxygene uses with instead of let to introduce a new variable:

from o in list with name := o.Name where ...
from o in list let name := o.Name where ...

Oxygene uses a more readable "order by" for sorting, while C# uses the concatenation "orderby":

from o in list order by o.name descending
from o in list orderby o.name descending

Oxygene also supports distinct, reverse, skip and take as LINQ operators, which are not available in C#.

LINQ from Swift, Java and Go

While the Swift, Java and Go languages do not have a language integrated query syntax, the LINQ operators themselevs can still be used using regular lambda/closure syntax:

let sortedAdults = people.Where({ $0.Age > 18 }).OrderBy({ $0.Name })
var sortedAdults = people.Where(p -> p.Age > 18).OrderBy(p -> p.Name);

Queryable Sequences

Depending on the sequence type, LINQ expressions can be processed by the compiler in two ways. For normal sequences, each sub-expression is mapped to simply call to an (extension) method on the sequence, as detailed below. However, for Queryable Sequences, the LINQ expression is converted to meta data that can be interpreted at runtime – for example for translating a LINQ expression directly to an SQL query run against a database.

Mapping

Each LINQ expression maps to an (extension) method on the Sequence type, under the hood. Implementations for these methods are provided by the framework, on .NET, and by the Elements libraries (libToffee, Cooper.jar and Island RTL) on the other platforms.

  • distinct – maps to .Distinct()
  • group X by Y/group by Y select x – maps to .GroupBy()
  • from X in Y (inner from) – maps to .SelectMany() with optional Cast<T> if the type is specified; the result is turned into a special anonymous class where both original and new are available.
  • join on X equals Y – maps to .Join()
  • order by X – maps to .OrderBy, secondary order to .ThenBy()
  • order by X descending – maps to .OrderByDescending, secondary order to .ThenByDescending()
  • reverse – maps to .Reverse()
  • where X – maps to .Where()
  • select X – maps to .Select()
  • skip X – maps to .Skip()
  • skip while X – maps to .SkipWhile()
  • take X – maps to .Take()
  • take while X – maps to .TakeWhile()
  • with (Oxygene) and let (C#) – maps to .Select() with a special anonymous that makes both the original and the new variable available.

See Also