Какая история с ExpressionType.Assign?

У меня создалось впечатление, что назначение не возможно внутри лямбда-выражения. Например, следующий (по общему признанию, не очень полезный) код

Expression<Action<int, int>> expr = (x, y) => y = x;

Производит ошибку компилятора

An expression tree may not contain an assignment operator

И все же, согласно документации Microsoft, можно программно создать выражение присваивания с помощью Expression.Assign. Если я не ошибаюсь, следующий код создает эквивалент Expression:

ParameterExpression xparam = Expression.Parameter(typeof(int), "x");
ParameterExpression yparam = Expression.Parameter(typeof(int), "y");
BinaryExpression body = Expression.Assign(yparam, xparam);
var expr = Expression.Lambda<Action<int, int>>(body, xparam, yparam);
var cexpr = expr.Compile();

В этом случае компилятор не жалуется. Я чувствую, что здесь отсутствует какое-то важное различие.

Ответы

Ответ 1

Ответ

usr правильный; несколько расшириться:

Вам не хватает важного различия, вам не хватает важного измерения: время.

Если вы внимательно посмотрите на документацию, вы заметите, что в .NET 4.0 был добавлен Assign node.

Деревья выражений были добавлены в С# 3.0, который поставляется с .NET 3.5.

Команда, владеющая библиотекой дерева выражений, добавила к ней множество функций с момента отправки .NET 3.5. Использование этих функций, чтобы больше выражений находилось в дереве выражений на языке С#, не делало разрезание для С# 4.0 или С# 5.0. Нет причин не выполнять эту функцию; это совершенно разумная особенность. Но разработчикам языка не требуется причина, чтобы не выполнять функцию; они требуют повода потратить бюджет на функцию.

В этом случае более богатые деревья выражений на С# просто не сделали его достаточно высоким в списке приоритетов. Если вы хотите, чтобы эта функция имела более высокий приоритет, вы можете открыть проблему на connect.microsoft.com и запросить ее. Ваш запрос, скорее всего, будет реализован, если вы включите убедительный сценарий для этой функции.

Ответ 2

Вы ничего не понимаете. С# намеренно ограничивает типы деревьев выражений, которые он может генерировать для вас. Нет принципиальной причины, по которой у нее не было этой возможности. Он просто не был вложен. (Создание функций отнимает ресурсы. Предположите, что у вас есть async/await или выражения дерева выражений? Очевидно, что первый вариант более полезен.).

Вы также не можете генерировать другие выражения, такие как if или while, хотя они находятся в API дерева выражений, начиная с .NET 4. (Теперь вы можете создавать и компилировать сложные потоки управления с деревьями выражений).