Деревья выражений — параметр не сопоставлен из аргумента лямбда-функции с параметром выражения

#c# #lambda #expression-trees

#c# #лямбда #деревья выражений

Вопрос:

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

         public static Func<int, bool> Generate_IsEven_Func()
        {
            var numParam = Expression.Parameter(typeof(int), "numParam");
            var returnValue = Expression.Variable(typeof(bool), "returnValue");

            var consoleWL = typeof(Console).GetMethod(nameof(Console.WriteLine), new[] { typeof(int) });
            
            var body = Expression.Block(
                 // Scoping the variables
                 new[] { numParam, returnValue },

                 // Printing the current value for numParam
                 Expression.Call(
                     null,
                     consoleWL,
                     numParam
                     ),

                 // Assign the default value to return
                 Expression.Assign(returnValue, Expression.Constant(false, typeof(bool))),

                 // If the numParam is even the returnValue becomes true
                 Expression.IfThen(
                            Expression.Equal(
                                Expression.Modulo(
                                    numParam,
                                    Expression.Constant(2, typeof(int))
                                    ),
                                Expression.Constant(0, typeof(int))
                                ),
                            Expression.Assign(returnValue, Expression.Constant(true, typeof(bool)))
                        ),

                 // value to return
                 returnValue
                );

            var lambda = Expression.Lambda<Func<int, bool>>(body, numParam).Compile();
            return lambda;
        }
  

Когда я вызываю вновь созданную лямбда-функцию, оказывается, что значение, которое я передаю в качестве аргумента, не «сопоставлено» с соответствующим параметром выражения — numParam . Внутри блочного выражения я вызываю Console.WriteLine метод для проверки текущего значения numParam , и каждый раз оно равно 0:

   var isEvenMethod = Generate_IsEven_Func();
  var cond = isEvenMethod(21);
  Console.WriteLine(cond);

  // Prints:
  // 0
  // True
  

Ответ №1:

Вы не должны включать numParam в массив переменных, которые вы передаете в качестве первого параметра Expression.Block(...) — прямо сейчас вы, по сути, создаете новую numParam переменную внутри блока, которая не связана с numParam параметром, переданным лямбда. Поскольку переменная автоматически инициализируется значением по умолчанию int (0), это объясняет вывод, который вы видите.

Комментарии:

1. Это сработало, большое спасибо! Эта область видимости все еще немного неясна для меня, когда дело доходит до деревьев выражений.