Какая история с 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. (Теперь вы можете создавать и компилировать сложные потоки управления с деревьями выражений).