Language Integrated Query (LINQ, pronounced "link") is a Microsoft .NET framework component that adds native data querying abilities to .NET languages, originally released as a major part of .NET Framework 3.5 in 2007.

LINQ extends the language by the addition of query expressions, which are akin to SQL statements, and can be used to conveniently extract and process data from arrays, enumerable classes, XML documents, relational databases, and third-party data sources. Other uses, which utilize query expressions as a general framework for readably composing arbitrary computations, include the construction of event handlers or monadic parsers. It also defines a set of method names (called standard query operators, or standard sequence operators), along with translation rules used by the compiler to translate query syntax expressions into expressions using fluent-style (called method syntax by Microsoft) with these method names, lambda expressions and anonymous types.

Architecture

Standard query operator API In what follows, the descriptions of the operators are based on the application of working with collections. Many of the operators take other functions as arguments. These functions may be supplied in the form of a named method or anonymous function.

The set of query operators defined by LINQ is exposed to the user as the Standard Query Operator (SQO) application programming interface (API). The query operators supported by the API are:

Select The Select operator performs a projection on the collection to select interesting aspects of the elements. The user supplies an arbitrary function, in the form of a named or lambda expression, which projects the data members. The function is passed to the operator as a delegate. This implements the higher-order function.

Where The Where operator allows the definition of a set of predicate rules that are evaluated for each object in the collection, while objects that do not match the rule are filtered away. The predicate is supplied to the operator as a delegate. This implements the higher-order function.

SelectMany For a user-provided mapping from collection elements to collections, semantically two steps are performed. First, every element is mapped to its corresponding collection. Second, the result of the first step is flattened by one level. Select and Where are both implementable in terms of SelectMany, as long as singleton and empty collections are available. The translation rules mentioned above still make it mandatory for a LINQ provider to provide the other two operators. This implements the higher-order function.

Sum, Min, Max, Average These operators optionally take a function that retrieves a certain numeric value from each element in the collection and uses it to find the sum, minimum, maximum or average values of all the elements in the collection, respectively. Overloaded versions take no function and act as if the identity is given as the lambda.

Aggregate A generalized Sum/Min/Max. This operator takes a function that specifies how two values are combined to form an intermediate or the final result. Optionally, a starting value can be supplied, enabling the result type of the aggregation to be arbitrary. Furthermore, a finalization function, taking the aggregation result to yet another value, can be supplied. This implements the higher-order function.

Join, GroupJoin The Join operator performs an inner join on two collections, based on matching keys for objects in each collection. It takes two functions as delegates, one for each collection, that it executes on each object in the collection to extract the key from the object. It also takes another delegate in which the user specifies which data elements, from the two matched elements, should be used to create the resultant object. The GroupJoin operator performs a group join. Like the Select operator, the results of a join are instantiations of a different class, with all the data members of both the types of the source objects, or a subset of them.

Take, TakeWhile The Take operator selects the first n objects from a collection, while the TakeWhile operator, which takes a predicate, selects those objects that match the predicate (stopping at the first object that doesn't match it).

Skip, SkipWhile The Skip and SkipWhile operators are complements of Take and TakeWhile - they skip the first n objects from a collection, or those objects that match a predicate (for the case of SkipWhile).

OfType The OfType operator is used to select the elements of a certain type.

Concat The Concat operator concatenates two collections.

OrderBy, ThenBy The OrderBy operator is used to specify the primary sort ordering of the elements in a collection according to some key. The default ordering is in ascending order, to reverse the order, the OrderByDescending operator is to be used. ThenBy and ThenByDescending specifies subsequent ordering of the elements. The function to extract the key value from the object is specified by the user as a delegate.

Reverse The Reverse operator reverses a collection.

GroupBy The GroupBy operator takes a function that extracts a key value and returns a collection of System.Linq.IGrouping<K, V> objects, for each distinct key value. The System.Linq.IGrouping<K, V> objects can then be used to enumerate all the objects for a particular key value.

Distinct The Distinct operator removes duplicate instances of an object from a collection. An overload of the operator takes an equality comparator object which defines the criteria for distinctness.

Union, Intersect, Except These operators are used to perform a union, intersection and difference operation on two sequences, respectively. Each has an overload which takes an equality comparator object which defines the criteria for element equality.

SequenceEqual The SequenceEqual operator determines whether all elements in two collections are equal and in the same order.

First, FirstOrDefault, Last, LastOrDefault These operators take a predicate. The First operator returns the first element for which the predicate yields true, or, if nothing matches, throws an exception. The FirstOrDefault operator is like the First operator except that it returns the default value for the element type (usually a null reference) in case nothing matches the predicate. The Last operator retrieves the last element to match the predicate, or throws an exception in case nothing matches. The LastOrDefault returns the default element value if nothing matches.

Single, SingleOrDefault The Single operator takes a predicate and returns the element that matches the predicate. An exception is thrown, if none or more than one element match the predicate.

The SingleOrDefault operator takes a predicate and return the element that matches the predicate. If more than one element matches the predicate, an exception is thrown. If no element matches the predicate, a default value is returned.

ElementAt The ElementAt operator retrieves the element at a given index in the collection.

Any, All The Any operator checks, if there are any elements in the collection matching the predicate. It does not select the element, but returns true if at least one element is matched. An invocation of any without a predicate returns true if the collection non-empty. The All operator returns true if all elements match the predicate.

Contains The Contains operator checks, if the collection contains a given element.

Count The Count operator counts the number of elements in the given collection. An overload taking a predicate, counts the number of elements matching the predicate.

Convert a Collection into another type

The standard query operator API also specifies certain operators that convert a collection into another type: AsEnumerable: Statically types the collection as an System.Collections.Generic.IEnumerable<T>. AsQueryable: Statically types the collection as an System.Linq.IQueryable<T>. ToArray: Creates an array T[] from the collection. ToList: Creates a System.Collections.Generic.List<T> from the collection. ToDictionary: Creates a System.Collections.Generic.Dictionary<K, V> from the collection, indexed by the key K. A user supplied projection function extracts a key from each element. ToLookup: Creates a System.Linq.Lookup<K, V> from the collection, indexed by the key K. A user supplied projection function extracts a key from each element. Cast: converts a non-generic System.Collections.IEnumerable collection to one of System.Collections.Generic.IEnumerable<T> by casting each element to type T. Alternately converts a generic System.Collections.Generic.IEnumerable<T> to another generic System.Collections.Generic.IEnumerable<R> by casting each element from type T to type R. Throws an exception in any element cannot be cast to the indicated type. OfType: converts a non-generic System.Collections.IEnumerable collection to one of System.Collections.Generic.IEnumerable<T>. Alternately converts a generic System.Collections.Generic.IEnumerable<T> to another generic System.Collections.Generic.IEnumerable<R> by attempting to cast each element from type T to type R. In both cases, only the subset of elements successfully cast to the target type are included. No exceptions are thrown.

Language extensions While LINQ is mainly implemented as a library for .NET Framework 3.5, it also defines optional language extensions that make queries a first-class language construct and provide syntactic sugar for writing queries. These language extensions have initially been implemented in C# 3.0, VB 9.0, F# and Oxygene, with other languages like Nemerle having announced preliminary support. The language extensions include: Query syntax: A language is free to choose a query syntax that it will recognize natively. These language keywords must be translated by the compiler to appropriate LINQ method calls. Implicitly typed variables: This enhancement allows variables to be declared without specifying their types. The languages C# 3.0 and Oxygene declare them with the var keyword. In VB9.0, the Dim keyword without type declaration accomplishes the same. Such objects are still strongly typed; for these objects the compiler infers the types of variables via type inference, which allows the results of the queries to be specified and defined without declaring the type of the intermediate variables. Anonymous types: Anonymous types allow classes that contain only data-member declarations to be inferred by the compiler. This is useful for the Select and Join operators, whose result types may differ from the types of the original objects. The compiler uses type inference to determine the fields contained in the classes and generates accessors and mutators for these fields. Object initializer: Object initializers allow an object to be created and initialized in a single scope, as required for Select and Join operators. Lambda expressions: Lambda expressions allow predicates and other projection functions to be written inline with a concise syntax, and support full lexical closure. They are captured into parameters as delegates or expression trees depending on the Query Provider.

For example, in the query to select all the objects in a collection with SomeProperty less than 10,

using System; using System.Collections.Generic;

IEnumerable<MyObject> SomeCollection = /* something here */;

IEnumerable<MyObject> results = from c in SomeCollection where c.SomeProperty < 10 select new {c.SomeProperty, c.OtherProperty};

foreach (MyObject result in results) { Console.WriteLine(result); }

the types of variables result, c and results all are inferred by the compiler in accordance to the signatures of the methods eventually used. The basis for choosing the methods is formed by the query expression-free translation result

using System; using System.Collections.Generic;

IEnumerable<MyObject> results = SomeCollection .Where(c => c.SomeProperty < 10)