Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Деревья выражений представляют код в структуре данных, например в виде дерева, где каждый узел является выражением, например вызов метода или двоичная операция, например x < y
.
Если вы использовали LINQ, у вас есть опыт работы с богатой библиотекой, в которой Func
типы являются частью набора API. (Если вы не знакомы с LINQ, вероятно, хотите прочитать руководство по LINQ и статью о лямбда-выражениях перед этим. Деревья выражений обеспечивают более расширенное взаимодействие с аргументами, которые являются функциями.
При написании аргументов функций вы обычно используете лямбда-выражения при создании запросов LINQ. В типичном запросе LINQ эти аргументы функции преобразуются в делегат, который создает компилятор.
Вы уже пишете код, использующий деревья выражений. API LINQ Entity Framework принимают деревья выражений в качестве аргументов для шаблона выражения запроса LINQ. Это позволяет Entity Framework переводить запрос, написанный на C# в SQL, который выполняется в ядре СУБД. Другим примером является Moq, который является популярной платформой макетирования для .NET.
Если требуется более расширенное взаимодействие, необходимо использовать деревья выражений. Деревья выражений представляют код как структуру, которую вы проверяете, изменяете или выполняете. Эти средства позволяют управлять кодом во время выполнения. Вы пишете код, который проверяет выполнение алгоритмов или внедряет новые возможности. В более сложных сценариях можно изменять выполняемые алгоритмы и даже переводить выражения C# в другую форму для выполнения в другой среде.
Вы компилируете и запускаете код, представленный деревьями выражений. Создание и выполнение деревьев выражений обеспечивает динамическое изменение исполняемого кода, выполнение запросов LINQ в различных базах данных и создание динамических запросов. Дополнительные сведения о деревьях выражений в LINQ см. в статье "Использование деревьев выражений для создания динамических запросов".
Деревья выражений также используются в среде исполнения динамических языков (DLR) для обеспечения взаимодействия между динамическими языками и .NET, а также чтобы компиляторы могли генерировать деревья выражений вместо промежуточного языка Microsoft (CIL). Дополнительные сведения о DLR см. в разделе "Обзор динамической языковой среды выполнения".
Вы можете поручить компилятору C# или Visual Basic создать для вас дерево выражений на основе анонимного лямбда-выражения или создать деревья выражений вручную с помощью пространства имен System.Linq.Expressions.
Когда лямбда-выражение назначается переменной типа Expression<TDelegate>, компилятор выдает код для создания дерева выражений, представляющего лямбда-выражение.
В следующих примерах кода показано, как создать дерево выражений C#, представляющее лямбда-выражение num => num < 5
.
Expression<Func<int, bool>> lambda = num => num < 5;
В коде создаются деревья выражений. Дерево создается путем создания каждого узла и присоединения узлов к структуре дерева. Вы узнаете, как создавать выражения в статье о создании деревьев выражений.
Деревья выражений неизменяемы. Если вы хотите изменить дерево выражений, необходимо создать новое дерево выражений путем копирования существующего и замены узлов в нем. Вы используете посетителя дерева выражений для обхода существующего дерева выражений. Дополнительные сведения см. в статье о переводе деревьев выражений.
После создания дерева выражений выполните код, представленный деревом выражений.
Ограничения
Компилятор C# создает деревья выражений только из выражений-лямбда и однострочных лямбда-функций. Невозможно разобрать лямбда-выражения (или многострочные лямбда-выражения). Дополнительные сведения о лямбда-выражениях в C#см. в лямбда-выражениях.
Существуют некоторые новые элементы языка C#, которые не преобразуются в деревья выражений. Деревья выражений не могут содержать await
выражения или async
лямбда-выражения. Многие функции, добавленные в C# 6 и более поздних версий, не отображаются точно так же, как и в деревьях выражений. Вместо этого новые функции предоставляются в деревах выражений в эквивалентном, более раннем синтаксисе, где это возможно. Остальные конструкции недоступны. Это означает, что код, который интерпретирует деревья выражений, работает так же, как при появлении новых возможностей языка. Однако даже с этими ограничениями деревья выражений позволяют создавать динамические алгоритмы, основанные на интерпретации и изменении кода, представленного как структура данных. Она позволяет расширенным библиотекам, таким как Entity Framework, выполнять то, что они делают.
Деревья выражений не поддерживают новые типы узлов выражений. Это было бы критическое изменение для всех библиотек, интерпретирующих деревья выражений, чтобы ввести новые типы узлов. В следующем списке содержатся большинство элементов языка C#, которые нельзя использовать:
- Условные методы удалены из выходных данных
-
base
доступ - Выражения групп методов, включая адрес
&
() группу методов и анонимные выражения методов - Ссылки на локальные функции
- Операторы, включая присвоение (
=
) и выражения телесного выражения оператора - Частичные методы только с объявлением определения
- Небезопасные операции указателя
-
dynamic
операции -
Операторы объединения с
null
илиdefault
буквальной левой частью, оператор присваивания объединения null и оператор распространения null (?.
) - Инициализаторы многомерного массива, индексированные свойства и инициализаторы словаря
- коллекционные выражения
-
throw
Выражения -
Доступ к членам
static virtual
илиabstract
интерфейса - Лямбда-выражения с атрибутами
- Интерполированные строки
- Преобразования строк UTF-8 или строковые литералы UTF-8
- Вызовы методов с помощью аргументов переменной, именованных аргументов или необязательных аргументов
- Выражения, использующие System.Index или System.Range, оператор индекса "с конца" (
^
) или выражения диапазона (..
) -
async
лямбда-выражения илиawait
выражения, включаяawait foreach
иawait using
-
Кортежные литералы, преобразования кортежей, кортеж
==
или!=
, илиwith
выражения -
Отбрасываниe (
_
), деконструктивное присваивание, оператор сопоставления поis
шаблону или выражение сопоставления поswitch
шаблону - ВЫЗОВ COM с
ref
опущенными аргументами -
ref
,in
илиout
параметры, возвращаемые значения,ref
out
аргументы или любые значенияref struct
типа