# Programmation C sharp/Expression de requête

Les versions récentes du langage C sharp permettent d'utiliser une expression de requête sur un ensemble de données itérables en utilisant une syntaxe similaire à celle des requêtes de base de données. Cette intégration de la syntaxe de requête dans le langage s'appelle en anglais Language Integrated Query (LINQ).

## Syntaxe

Le mot clé from sert à introduire une expression de requête. Il est suivi par le nom de la variable qui référencera les valeurs itérées, du mot-clé in, de l'ensemble de données itéré et d'un nombre d'instructions de requête (sélection, groupement, tri, etc.).
L'ensemble de données doit implémenter l'interface IEnumerable<T> ou une interface dérivée comme IQueryable<T> ; le type T est alors utilisé par le compilateur pour définir le type générique pour la variable qui référencera les valeurs itérées. Si l'ensemble de données implémente l'interface IEnumerable (sans type d'élément spécifié, comme la classe ArrayList), le type d'élément doit être spécifié.
En clair, cela transforme un ensemble IEnumerable en un autre ensemble IEnumerable itérant des éléments du même type (ou IGrouping<K,T> pour une clause de groupement), mais filtrant et éventuellement réordonnant les éléments de l'ensemble initial.
Exemple : N'afficher que les entiers pairs d'un tableau
La requête n'est pas exécutée immédiatement, mais lors de l'itération avec la boucle foreach. Elle est également déclenchée par l'appel à une méthode de l'interface IEnumerable nécessitant le parcours des éléments :
* Pour obtenir des statistiques sur les résultats de la requête :
    Count, Max, Average, First...
* Pour convertir les résultats en tableau ou collection :
    ToArray, ToList...
La requête semble réaliser l'équivalent d'une boucle combinée à une condition. Cependant elle permet également de trier les résultats, de les regrouper, et il est possible de passer la requête à une fonction ayant besoin d'un ensemble de valeurs itérables. Ces cas d'utilisations seraient beaucoup plus complexes à réaliser sans la syntaxe des expressions de requête.
Quand l'ensemble de données implémente l'interface IEnumerable sans type d'élément spécifié, comme la classe ArrayList par exemple, le type d'élément doit être spécifié pour la variable comme dans l'exemple suivant :

## Clauses de requête

Différentes clauses suivent la définition de la source de données, traitées dans l'ordre, chacune introduite par un mot-clé :
* where pour filtrer les données avec une condition,
* join pour joindre les résultats avec une autre source de données,
* group pour grouper les résultats (type T) ayant une valeur commune (la clé K) en objets de type IGrouping<K,T>,
* orderby pour itérer les résultats dans un ordre particulier,
* select pour définir les résultats à itérer (objet, structure, calcul...).

## Filtre

Le filtrage des éléments est introduit par le mot-clé where suivi d'une expression booléenne définissant la condition pour que l'élément apparaisse dans l'itération des résultats de la requête.
Plusieurs clauses where peuvent être utilisées à la suite permettant de valider toutes les conditions, comme l'opérateur et utilisé dans l'exemple précédent.
Exemple équivalent au précédent :

## Sélection

La clause select définit la valeur retournée à chaque itération des résultats de la requête, et détermine aussi le type du paramètre générique des résultats itérables.

## Tri

Les résultats peuvent être triant en utilisant la clause orderby. Ce mot-clé est suivi d'une liste d'expressions définissant chacune la valeur de critère pour définir l'ordre des résultats. Chacun de ces critères est optionnellement suivi du mot-clé ascending pour un tri dans l'ordre croissant, ou du mot-clé descending pour un tri dans l'ordre décroissant. S'il n'est pas spécifié, le tri est en ordre croissant.
Exemple simple :
Exemple avec un tableau d'objets utilisé dans une requête où second critère de tri est spécifié en cas d'égalité pour le premier :

## Regroupement

Le regroupement est introduit par le mot-clé group produisant une séquence d'objets de classe implémentant l'interface IGrouping<K,T>. Cette interface permet d'accéder à la clé K commune aux éléments membres du groupe par la propriété Key, et étend l'interface IEnumerable<T>. Cela signifie qu'une instance de cette interface permet d'itérer sur les éléments membres du groupe.
Le mot-clé group est suivi de l'objet groupé (définissant T pour l'interface générique IGrouping<K,T>), du mot-clé by suivi de la clé de regroupement (définissant K pour l'interface générique IGrouping<K,T>).
Exemple : Regrouper les dates d'un planning annuel par mois
Pour effectuer des opérations supplémentaires sur les groupes, il faut ajouter une clause into pour définir le nom référençant le groupe, comme dans l'exemple suivant :
Deux boucles imbriquées sont nécessaires : la boucle de premier niveau itère sur les groupes, et la boucle de second niveau itère sur les membres de chaque groupe, comme illustré ci-dessous :
L'exemple affiche les dates groupées par mois :
La clé de regroupement est une expression quelconque, et peut créer un nouvel objet pour regrouper plusieurs critères de regroupement.

## Combinaison de sources de données
### Jointure

Il est possible de faire une jointure libre en utilisant plusieurs clauses from sur des sources de données indépendantes, comme dans l'exemple ci-dessous.

### Sous-requête

Il est possible de créer une sous-requête pour sélectionner des données d'une collection stockée dans un objet. Pour cela, une clause from est ajoutée à la première, référençant la variable de celle-ci.
Exemple :