Partager via


Arborescences de l’expression

Les arborescences d’expressions représentent du code dans une structure de données de type arborescence, où chaque nœud est une expression, par exemple, un appel de méthode ou une opération binaire telle que x < y.

Si vous avez utilisé LINQ, vous avez de l’expérience avec une bibliothèque riche où les Func types font partie de l’ensemble d’API. (Si vous n’êtes pas familiarisé avec LINQ, vous souhaitez probablement lire le didacticiel LINQ et l’article sur les expressions lambda avant celle-ci.) Les arborescences d’expressions fournissent une interaction plus riche avec les arguments qui sont des fonctions.

Vous écrivez des arguments de fonction, généralement à l’aide d’expressions lambda, lorsque vous créez des requêtes LINQ. Dans une requête LINQ classique, ces arguments de fonction sont transformés en délégué que le compilateur crée.

Vous écrivez déjà du code qui utilise des arborescences d’expressions. Les API LINQ d’Entity Framework acceptent les arborescences d’expressions comme arguments pour le modèle d’expression de requête LINQ. Cela permet à Entity Framework de traduire la requête que vous avez écrite en C# en SQL qui s’exécute dans le moteur de base de données. Un autre exemple est Moq, qui est un framework de simulation populaire pour .NET.

Lorsque vous souhaitez avoir une interaction plus riche, vous devez utiliser des arborescences d’expressions. Les arborescences d’expressions représentent le code sous la forme d’une structure que vous examinez, modifiez ou exécutez. Ces outils vous permettent de manipuler du code pendant l’exécution. Vous écrivez du code qui examine les algorithmes en cours d’exécution ou injecte de nouvelles fonctionnalités. Dans des scénarios plus avancés, vous modifiez les algorithmes en cours d’exécution et vous convertissez même des expressions C# dans un autre formulaire pour l’exécution dans un autre environnement.

Vous compilez et exécutez du code représenté par des arborescences d’expressions. La création et l’exécution d’arborescences d’expressions permettent une modification dynamique du code exécutable, l’exécution de requêtes LINQ dans différentes bases de données et la création de requêtes dynamiques. Pour plus d’informations sur les arborescences d’expressions dans LINQ, consultez Comment utiliser des arborescences d’expressions pour générer des requêtes dynamiques.

Les arborescences d’expressions sont également utilisées dans le runtime de langage dynamique (DLR) pour fournir une interopérabilité entre les langages dynamiques et .NET et permettre aux enregistreurs du compilateur d’émettre des arborescences d’expressions au lieu du langage intermédiaire Microsoft (CIL). Pour plus d’informations sur le DLR, consultez Vue d’ensemble du runtime de langage dynamique.

Vous pouvez avoir le compilateur C# ou Visual Basic créer une arborescence d’expressions pour vous en fonction d’une expression lambda anonyme, ou vous pouvez créer manuellement des arborescences d’expressions à l’aide de l’espace System.Linq.Expressions de noms.

Lorsqu’une expression lambda est affectée à une variable de type Expression<TDelegate>, le compilateur émet du code pour générer une arborescence d’expressions qui représente l’expression lambda.

Les exemples de code suivants montrent comment le compilateur C# crée une arborescence d’expressions qui représente l’expression num => num < 5lambda.

Expression<Func<int, bool>> lambda = num => num < 5;

Vous créez des arborescences d’expressions dans votre code. Vous construisez l’arborescence en créant chaque nœud et en les intégrant dans une structure arborescente. Vous allez apprendre à créer des expressions dans l’article sur la création d’arborescences d’expressions.

Les arborescences d’expressions sont immuables. Si vous souhaitez modifier une arborescence d’expressions, vous devez construire une nouvelle arborescence d’expressions en copiant l’arborescence existante et en remplaçant les nœuds dans celui-ci. Vous utilisez un visiteur de l’arborescence d’expressions pour parcourir l’arborescence d’expressions existante. Pour plus d’informations, consultez l’article sur la traduction d’arborescences d’expressions.

Une fois que vous avez généré une arborescence d’expressions, vous exécutez le code représenté par l’arborescence d’expressions.

Limites

Le compilateur C# génère des arborescences d’expressions uniquement à partir des expressions lambda (ou des lambdas à ligne unique). Il ne peut pas analyser les lambdas d’instruction (ou les lambda multilignes). Pour plus d’informations sur les expressions lambda en C#, consultez Expressions lambda.

Il existe des éléments de langage C# plus récents qui ne se traduisent pas correctement en arborescences d’expressions. Les arborescences d’expressions ne peuvent pas contenir await d’expressions ou async d’expressions lambda. La plupart des fonctionnalités ajoutées en C# 6 et versions ultérieures n’apparaissent pas exactement comme écrites dans les arborescences d’expressions. Au lieu de cela, les fonctionnalités plus récentes sont exposées dans les arborescences d’expressions dans la syntaxe antérieure équivalente, le cas échéant. D'autres constructions ne sont pas disponibles. Cela signifie que le code qui interprète les arborescences d’expressions fonctionne de la même façon lorsque de nouvelles fonctionnalités de langage sont introduites. Toutefois, même avec ces limitations, les arborescences d’expressions vous permettent de créer des algorithmes dynamiques qui s’appuient sur l’interprétation et la modification du code représenté sous forme de structure de données. Il permet aux bibliothèques enrichies telles que Entity Framework d’accomplir ce qu’elles font.

Les arborescences d’expressions ne prennent pas en charge les nouveaux types de nœuds d’expression. Il s’agirait d’un changement cassant pour toutes les bibliothèques interprétant des arborescences d’expressions afin d’introduire de nouveaux types de nœuds. La liste suivante inclut la plupart des éléments de langage C# qui ne peuvent pas être utilisés :