Partager via


Relations de type dans les opérations de requête LINQ (C#)

Pour écrire des requêtes efficacement, vous devez comprendre comment les types de variables dans une opération de requête complète se rapportent tous les uns aux autres. Si vous comprenez ces relations, vous comprendrez plus facilement les exemples LINQ et les exemples de code dans la documentation. En outre, vous comprendrez ce qui se produit lorsque les variables sont implicitement typées à l’aide de var.

Les opérations de requête LINQ sont fortement typées dans la source de données, dans la requête elle-même et dans l’exécution de la requête. Le type des variables de la requête doit être compatible avec le type des éléments de la source de données et avec le type de la variable d’itération dans l’instruction foreach . Ce typage fort garantit que les erreurs de type sont interceptées lors de la compilation, afin qu'elles puissent être corrigées avant que les utilisateurs ne les rencontrent.

Pour illustrer ces relations de type, la plupart des exemples qui suivent utilisent la saisie explicite pour toutes les variables. Le dernier exemple montre comment les mêmes principes s’appliquent même lorsque vous utilisez la saisie implicite à l’aide varde .

Requêtes qui ne transforment pas les données sources

L’illustration suivante montre une opération de requête LINQ to Objects qui n’effectue aucune transformation sur les données. La source contient une séquence de chaînes et la sortie de la requête est également une séquence de chaînes.

Diagramme montrant la relation des types de données dans une requête LINQ.

  1. L’argument type de la source de données détermine le type de la variable de plage.
  2. Le type de l’objet sélectionné détermine le type de la variable de requête. Ici, name est une chaîne. Par conséquent, la variable de requête est un IEnumerable<string>.
  3. La variable de requête est itérée dans l’instruction foreach . Étant donné que la variable de requête est une séquence de chaînes, la variable d’itération est également une chaîne.

Requêtes qui transforment les données sources

L’illustration suivante montre une opération de requête LINQ to SQL qui effectue une transformation simple sur les données. La requête prend une séquence d’objets Customer comme entrée et sélectionne uniquement la Name propriété dans le résultat. Comme Name il s’agit d’une chaîne, la requête produit une séquence de chaînes en tant que sortie.

Diagramme montrant une requête qui transforme le type de données.

  1. L’argument type de la source de données détermine le type de la variable de plage.
  2. L’instruction select retourne la Name propriété au lieu de l’objet complet Customer . Étant donné qu’il Name s’agit d’une chaîne, l’argument de type de l’argument custNameQuery est string, et non Customer.
  3. Comme custNameQuery il s’agit d’une séquence de chaînes, la variable d’itération de la foreach boucle doit également être un string.

L’illustration suivante montre une transformation légèrement plus complexe. L’instruction select retourne un type anonyme qui capture seulement deux membres de l’objet d’origine Customer .

Diagramme montrant une requête plus complexe qui transforme le type de données.

  1. L’argument de type de la source de données est toujours le type de la variable de plage dans la requête.
  2. Étant donné que l’instruction select produit un type anonyme, la variable de requête doit être implicitement typée à l’aide de var.
  3. Étant donné que le type de la variable de requête est implicite, la variable d’itération dans la foreach boucle doit également être implicite.

Laisser le compilateur déduire les informations de type

Bien que vous compreniez les relations de type dans une opération de requête, vous avez la possibilité de laisser le compilateur effectuer tout le travail pour vous. La var de mot clé peut être utilisée pour n’importe quelle variable locale dans une opération de requête. L’illustration suivante est similaire à l’exemple 2 abordé précédemment. Toutefois, le compilateur fournit le type fort pour chaque variable dans l’opération de requête.

Diagramme montrant le flux de type avec saisie implicite.

LINQ et types génériques (C#)

Les requêtes LINQ sont basées sur des types génériques. Vous n’avez pas besoin d’une connaissance approfondie des génériques avant de commencer à écrire des requêtes. Toutefois, vous pouvez comprendre deux concepts de base :

  1. Lorsque vous créez une instance d’une classe de collection générique telle que List<T>, vous remplacez le « T » par le type d’objets que la liste contiendra. Par exemple, une liste de chaînes est exprimée en tant que List<string>, et une liste d’objets Customer est exprimée en tant que List<Customer>. Une liste générique est fortement typée et offre de nombreux avantages sur les collections qui stockent leurs éléments sous Object. Si vous essayez d’ajouter un Customer à un List<string>, vous obtiendrez une erreur au moment de la compilation. Il est facile d’utiliser des collections génériques, car vous ne devez pas effectuer un cast de type à l’exécution.
  2. IEnumerable<T> est l’interface qui permet d’énumérer les classes de collection génériques à l’aide de l’instruction foreach . Les classes de collection génériques prennent en charge IEnumerable<T> de la même façon que les classes de collection non génériques telles que ArrayList prennent en charge IEnumerable.

Pour plus d’informations sur les génériques, consultez Génériques.

Variables de type IEnumerable<T> dans les requêtes LINQ

Les variables de requête LINQ sont typées comme IEnumerable<T> ou un type dérivé tel que IQueryable<T>. Lorsque vous voyez une variable de requête typée comme IEnumerable<Customer>, cela signifie simplement que la requête, lorsqu’elle est exécutée, produit une séquence de zéro ou plus Customer d’objets.

IEnumerable<Customer> customerQuery = from cust in customers
                                      where cust.City == "London"
                                      select cust;

foreach (Customer customer in customerQuery)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

Laisser le compilateur gérer les déclarations de type générique

Si vous préférez, vous pouvez éviter la syntaxe générique à l’aide du mot clé var . Le var mot clé indique au compilateur de déduire le type d’une variable de requête en examinant la source de données spécifiée dans la from clause. L’exemple suivant génère le même code compilé que l’exemple précédent :

var customerQuery2 = from cust in customers
                     where cust.City == "London"
                     select cust;

foreach(var customer in customerQuery2)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

Le var mot clé est utile lorsque le type de la variable est évident ou lorsqu’il n’est pas important de spécifier explicitement des types génériques imbriqués tels que ceux générés par des requêtes de groupe. En général, nous vous recommandons que si vous utilisez var, sachez qu’il peut rendre votre code plus difficile à lire pour d’autres utilisateurs. Pour plus d’informations, consultez Variables locales implicitement typées.