Лямбда-выражения и как объединить их?

Как я могу объединить два лямбда-выражения в одно использование ИЛИ?

Я попробовал следующее, но слияние их требует, чтобы я передал параметры в Выражение. Вызовите вызовы, однако я хочу, чтобы значение, переданное в новую лямбду, было передано на каждую дочернюю лямбду..

Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x < 0;
//Combines the lambdas but result in runtime error saying I need to pass in arguments
//However I want the argument passed into each child lambda to be whatever is passed into the new main lambda
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(Expression.Or(Expression.Invoke(func1), Expression.Invoke(func2)));

 //The 9 should be passed into the new lambda and into both child lambdas
 bool tst = lambda.Compile().Invoke(9);

Какие-либо идеи, как объединить два лямбда-выражения в одно и иметь аргументы дочерних лямбд быть идеей родителя?

14
задан Richard Friend 20 July 2010 в 08:56
поделиться

4 ответа

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

Если вы хотите объединить несколько операторов, вы можете:

Expression<Func<int, bool>> func1 = (x) => x > 5;
Expression<Func<int, bool>> func2 = (x) => x > 10;

var invocation = Expression.Invoke(func2, func1.Parameters.Cast<Expression>());
var expression = Expression.Lambda<Func<int, bool>>(Expression.OrElse(func1.Body, invocation), func1.Parameters);

Expression.Invoke создает InvocationExpression, который применяет параметры к вашей func2 .

Фактически, PredicateBuilder может быть всем, что вам нужно.

var predicate = PredicateBuilder.False<int>();
predicate = predicate.Or(x => x > 5);
predicate = predicate.Or(x => x > 10);

Я бы изменил " x> 5 или x> 10 ", это кажется странным для OR.

Надеюсь, что это поможет.

18
ответ дан 1 December 2019 в 13:07
поделиться

Звучит интересно ... Я не очень разбираюсь в лямбда-выражениях, но нашел эту статью . В разделе Исходный код PredicateBuilder является примером для или , который работает для меня:

public static Expression<Func<T, bool>> Or<T>(
                      this Expression<Func<T, bool>> expr1,
                      Expression<Func<T, bool>> expr2 )
{
  var invExpr = Expression.Invoke( expr2, expr1.Parameters.Cast<Expression>() );
  return Expression.Lambda<Func<T, bool>>
      ( Expression.OrElse( expr1.Body, invExpr ), expr1.Parameters );
}
1
ответ дан 1 December 2019 в 13:07
поделиться

Почему бы просто не сделать:

Func<int, bool> func1 = (x) => x > 5;
Func<int, bool> func2 = (x) => x > 10;

List<Func<int, bool>> funcs = new List<Func<int, bool>> { func1, func2 };

var value = 7;

Console.WriteLine(funcs.Any(x => x(value))); // OR
Console.WriteLine(funcs.All(x => x(value))); // AND

?

Это избавляет от необходимости возиться со сторонними библиотеками.

1
ответ дан 1 December 2019 в 13:07
поделиться

** edit: oops read over the OR thing, updated it ***

Hi,

Не уверен, хотите ли вы просто называть их отдельно или хотите объединить их с академической точки зрения.

Вы можете просто назвать их так:

bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){
    return f1(i1) || f2(i1);
}

Это поможет.

Или вы можете переписать это как

bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1);

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

Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR = 
(i1, f1, f2) => f1(i1) || f2(i1); 

Если вы хотите посмотреть на анатомию выражения, вы можете посмотреть эту статью, которую я написал: http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx

Просто передайте выражение в apadater и посмотрите, как оно строится.

Regards Gert-Jan

0
ответ дан 1 December 2019 в 13:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: