Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Expressions de requête
Les expressions de requête utilisent une syntaxe déclarative similaire à SQL ou XQuery pour interroger des System.Collections.Generic.IEnumerable<T> collections. Au moment de la compilation, la syntaxe de requête est convertie en appels de méthode vers l'implémentation des méthodes de requête standard du fournisseur LINQ. Les applications contrôlent les opérateurs de requête standard qui se trouvent dans la portée en spécifiant l’espace de noms approprié avec une directive using
. L’expression de requête suivante prend un tableau de chaînes, les regroupe en fonction du premier caractère de la chaîne et trie les groupes.
var query = from str in stringArray
group str by str[0] into stringGroup
orderby stringGroup.Key
select stringGroup;
Variables implicitement typées (var)
Vous pouvez utiliser le modificateur var pour indiquer au compilateur de déduire et d’affecter le type, comme illustré ici :
var number = 5;
var name = "Virginia";
var query = from str in stringArray
where str[0] == 'm'
select str;
Les variables déclarées comme var
étant fortement typées, tout comme les variables dont vous spécifiez explicitement le type. L'utilisation de var
permet de créer des types anonymes, mais uniquement pour les variables locales. Pour plus d’informations, consultez Variables locales implicitement typées.
Initialiseurs d’objets et de collections
Les initialiseurs d’objets et de collection permettent d’initialiser des objets sans appeler explicitement un constructeur pour l’objet. Les initialiseurs sont généralement utilisés dans les expressions de requête lorsqu’ils projetent les données sources dans un nouveau type de données. En supposant qu’une classe nommée Customer
avec public Name
et Phone
propriétés, l’initialiseur d’objet peut être utilisé comme dans le code suivant :
var cust = new Customer { Name = "Mike", Phone = "555-1212" };
Poursuivez avec votre classe Customer
, supposons qu’il existe une source de données appelée IncomingOrders
, et que pour chaque commande avec un OrderSize
important, vous souhaitez créer une nouvelle Customer
basée sur cette commande. Une requête LINQ peut être exécutée sur cette source de données et utiliser l’initialisation d’objet pour remplir une collection :
var newLargeOrderCustomers = from o in IncomingOrders
where o.OrderSize > 5
select new Customer { Name = o.Name, Phone = o.Phone };
La source de données peut avoir plus de propriétés définies que la Customer
classe, par OrderSize
exemple, mais avec l’initialisation de l’objet, les données retournées par la requête sont incorporées dans le type de données souhaité ; vous choisissez les données pertinentes pour votre classe. Par conséquent, vous disposez désormais d’un System.Collections.Generic.IEnumerable<T> contenant les nouveaux Customer
que vous vouliez. L’exemple précédent peut également être écrit dans la syntaxe de méthode LINQ :
var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });
À compter de C# 12, vous pouvez utiliser une expression de collection pour initialiser une collection.
Pour plus d’informations, consultez :
- Initialiseurs d’objets et de collections
- Syntaxe d’expression de requête pour les opérateurs de requête standard
Types anonymes
Le compilateur construit un type anonyme. Le nom du type est disponible uniquement pour le compilateur. Les types anonymes offrent un moyen pratique de regrouper temporairement un ensemble de propriétés dans un résultat de requête sans avoir à définir un type nommé distinct. Les types anonymes sont initialisés avec une nouvelle expression et un initialiseur d’objet, comme illustré ici :
select new {name = cust.Name, phone = cust.Phone};
À compter de C# 7, vous pouvez utiliser des tuples pour créer des types sans nom.
Méthodes d’extension
Une méthode d’extension est une méthode statique qui peut être associée à un type, afin qu’elle puisse être appelée comme s’il s’agissait d’une méthode d’instance sur le type. Cette fonctionnalité vous permet, en effet, d’ajouter de nouvelles méthodes à des types existants sans les modifier réellement. Les opérateurs de requête standard sont un ensemble de méthodes d’extension qui fournissent des fonctionnalités de requête LINQ pour tout type implémentant IEnumerable<T>.
Lambda Expressions
Une expression lambda est une fonction inline qui utilise l’opérateur =>
pour séparer les paramètres d’entrée du corps de la fonction et qui peut être convertie au moment de la compilation en délégué ou en arborescence d’expressions. Dans la programmation LINQ, vous rencontrez des expressions lambda lorsque vous effectuez des appels de méthode directe aux opérateurs de requête standard.
Expressions en tant que données
Les objets de requête sont composables, ce qui signifie que vous pouvez retourner une requête à partir d’une méthode. Les objets qui représentent des requêtes ne stockent pas la collection résultante, mais plutôt les étapes à suivre pour produire les résultats si nécessaire. L’avantage de renvoyer des objets de requête à partir de méthodes est qu’ils peuvent être composés ou modifiés. Par conséquent, toute valeur de retour ou out
paramètre d’une méthode qui retourne une requête doit également avoir ce type. Si une méthode matérialise une requête en un type concret List<T> ou Array, elle retourne les résultats de la requête au lieu de la requête elle-même. Une variable de requête retournée à partir d’une méthode peut toujours être composée ou modifiée.
Dans l’exemple suivant, la première méthode QueryMethod1
retourne une requête en tant que valeur de retour, et la deuxième méthode QueryMethod2
retourne une requête en tant que out
paramètre (returnQ
dans l’exemple). Dans les deux cas, il s’agit d’une requête retournée, et non de résultats de requête.
IEnumerable<string> QueryMethod1(int[] ints) =>
from i in ints
where i > 4
select i.ToString();
void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
returnQ = from i in ints
where i < 4
select i.ToString();
int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var myQuery1 = QueryMethod1(nums);
La requête myQuery1
est exécutée dans la boucle foreach suivante.
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}
Placez le pointeur de la souris sur myQuery1
pour voir son type.
Vous pouvez également exécuter la requête retournée QueryMethod1
directement, sans utiliser myQuery1
.
foreach (var s in QueryMethod1(nums))
{
Console.WriteLine(s);
}
Placez le pointeur de la souris sur l’appel à QueryMethod1
pour voir son type de retour.
QueryMethod2
retourne une requête comme valeur de son out
paramètre :
QueryMethod2(nums, out IEnumerable<string> myQuery2);
// Execute the returned query.
foreach (var s in myQuery2)
{
Console.WriteLine(s);
}
Vous pouvez modifier une requête à l’aide de la composition de requête. Dans ce cas, l’objet de requête précédent est utilisé pour créer un objet de requête. Ce nouvel objet retourne des résultats différents de ceux de l’objet de requête d’origine.
myQuery1 = from item in myQuery1
orderby item descending
select item;
// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}