Поддержка среды выполнения .NET для деревьев выражений
Существует большой список классов в среде выполнения .NET, которые работают с деревьями выражений. Полный список можно просмотреть в разделе System.Linq.Expressions. Вместо перечисления полного списка давайте посмотрим, как были разработаны классы среды выполнения.
Согласно принципам языка выражение — это блок кода, который выполняет вычисления и возвращает значение. Выражения могут быть простыми: константное выражение 1
возвращает константное значение 1. Они могут быть более сложными: выражение (-B + Math.Sqrt(B*B - 4 * A * C)) / (2 * A)
возвращает один корень квадратного уравнения (если у уравнения есть решение).
System.Linq.Expression и производные типы
Одна из трудностей при работе с деревьями выражений заключается в том, что выражения различных типов могут использоваться в программах в самых разных местах. Возьмем для примера выражение присваивания. В правой его части может быть константа, переменная, выражение вызова метода или иной элемент. Такая гибкость языка означает, что при обходе дерева выражения в его узлах вам могут встретиться различные типы выражений. Поэтому при работе с типом базового выражения это самый простой способ работы. Однако иногда этого недостаточно. На этот случай базовый класс Expression содержит свойство NodeType
. Возвращает значение ExpressionType
, которое представляет собой перечисление возможных типов выражений. После того как вы знаете тип узла, вы приведете его к такому типу и выполните определенные действия, зная тип узла выражения. Можно выполнить поиск узлов определенных типов, а затем работать со свойствами данного типа выражения.
Например, этот код выводит имя переменной для выражения доступа к переменной. В следующем коде показано, как проверка тип узла, а затем приведение к выражению доступа к переменной, а затем проверка свойства определенного типа выражения:
Expression<Func<int, int>> addFive = (num) => num + 5;
if (addFive is LambdaExpression lambdaExp)
{
var parameter = lambdaExp.Parameters[0]; -- first
Console.WriteLine(parameter.Name);
Console.WriteLine(parameter.Type);
}
Создание деревьев выражений
Класс System.Linq.Expression
также содержит множество статических методов для создания выражений. Эти методы создают узел выражения с помощью аргументов, предоставленных для его дочерних элементов. Таким образом, вы создаете выражение с конечных узлов. Например, следующий код создает выражение сложения:
// Addition is an add expression for "1 + 2"
var one = Expression.Constant(1, typeof(int));
var two = Expression.Constant(2, typeof(int));
var addition = Expression.Add(one, two);
На этом простом примере видно, что в создании деревьев выражений и работе с ними задействовано множество типов. Такая сложность необходима для предоставления широких возможностей словаря C#.
Навигация по API
Существуют типы узлов выражений, которые сопоставляются почти со всеми элементами синтаксиса языка C#. Каждый тип имеет определенные методы для конкретного типа элементов языка. Держать в голове приходится слишком многое. Вместо того чтобы попытаться запомнить все, вот методы, которые вы используете для работы с деревьями выражений:
- Просмотрите элементы перечисления
ExpressionType
, чтобы определить возможные узлы для анализа. Этот список помогает, когда вы хотите пройти и понять дерево выражений. - Просмотрите статические члены класса
Expression
, которые служат для создания выражения. С помощью этих методов можно создать выражение любого типа на основе набора дочерних узлов. - Обратите внимание на класс
ExpressionVisitor
, который служит для создания измененного дерева выражения.
Вы найдете больше, как вы посмотрите на каждую из этих трех областей. Неизменно, вы найдете то, что вам нужно, когда вы начинаете с одного из этих трех шагов.
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по