Почему можно «Я создаю то же дерево выражений вручную, которое производит моя прямая лямбда

Я прошел и бился головой об стену некоторое время, теперь искал различные фразы и ключевые слова, но я не могу найти ничего близкого к ответу, поэтому я надеюсь кто-то здесь может пролить свет.

В основном я работаю над довольно глубоким погружением в управление, создание и изменение деревьев выражений в C # 4.0

Я наткнулся на странную аномалию, я не могу понять

, если напишу что-то вроде этого

Expression<Func<string,string>> InsertAString = (Insert) => "This " + (Insert == "" ? "" : Insert + " ") + "That";

Когда я отлаживаю и смотрю на дерево выражений, оно выглядит примерно так

  • F (NodeType = Lambda )
    • Тело (NodeType = Добавить)
      • Влево (NodeType = Добавить)
        • Слева (NodeType = Constant, Value = "This")
        • Справа (NodeType = Conditional)
          • IfFalse (NodeType = Добавить)
            • Слева (NodeType = Parameter, Name = "Insert")
            • Справа (NodeType = Constant, Value = "")
          • IfTrue (NodeType = Constant, Value = "")
          • Тест (NodeType = Равно)
            • Слева (NodeType = Parameter, Name = "Insert")
            • Справа (NodeType = Constant, Value = "")
      • Справа (NodeType = Constant, Value = "That")
    • Параметры (Количество = 1)
      • Параметры [0] (NodeType = Parameter, Name = "Insert")

Я могу позвонить

Console.WriteLine(InsertAString.Compile()("Is Something In-between"));

И я выхожу, как и ожидал

«Это нечто среднее между этим»

Сейчас если я попытаюсь перестроить его вручную, используя статические методы базового класса Expression, я столкнусь с интересной проблемой. (Я разбил каждый шаг на отдельное выражение для целей отладки)

ParameterExpression Insert = Expression.Parameter(typeof(object), "Insert");
ConstantExpression This = Expression.Constant("This ");
ConstantExpression That = Expression.Constant("That");
ConstantExpression Space = Expression.Constant(" ");
ConstantExpression NoCharacter = Expression.Constant("");
BinaryExpression InsertPlusSpace = Expression.Add(Insert,Space);
BinaryExpression InsertEqualsNoCharacter = Expression.Equal(Insert,NoCharacter);
ConditionalExpression InsertPlusSpaceOrNothing = Expression.IfThenElse(InsertEqualsNoCharacter,NoCharacter,InsertPlusSpace);
BinaryExpression ThisPlusInsertPlusSpaceOrNothing = Expression.Add(This,InsertPlusSpaceOrNothing);
BinaryExpression ThisPlusInsertPlusSpaceOrNothingPlusThat = Expression.Add(ThisPlusInsertPlusSpaceOrNothing, That);
Lambda Lambda = Expression.Lambda(ThisPlusInsertPlusSpaceOrNothingPlusThat, Middle);
Expression<Func<string,string>> InsertAString = Lambda as Expression<Func<string,string>>   

Это на основе значений сгенерированного дерева выражений выше воссоздает такое же базовое дерево выражений, как указано выше (по крайней мере, с тем же «взглядом»)

Все проходит нормально, пока вы не дойдете до этой строки

BinaryExpression InsertPlusSpace = Expression.Add(Insert,Space);

. Компилятор выдает InvalidOperationException было unhandled

Бинарный оператор Add не определен для System.String и 'System.String'

Почему это так?

Почему, когда я позволяю C # преобразовывать лямбда-выражение в выражение, он явно использует Add NodeType, а отображение типов показывает, что он определенно использует System.String, когда я попробуйте сделать то же самое вручную, это не позволит продолжить код?

В заключение я даже пробовал следующее:

BinaryExpression InsertPlusSpace = Expression.MakeBinary( ExpressionType.Add,Insert,Space);

Та же ошибка.

Мне любопытно, почему это кажется хотя бы с тем, что я пока удалось обнаружить, что конкатенация строк в деревьях выражений работает только в том случае, если вы не пытаетесь вручную построить дерево выражений, которое добавляет константы и переменные типа System.String.

Заранее всем спасибо за ответы.

8
задан TofuBug 4 October 2010 в 19:05
поделиться