2008-10-02 2 views
2

Я пытаюсь объединить список таких функций.Объединить несколько выражений LINQ из массива

У меня есть это:

Func<int, bool>[] criteria = new Func<int, bool>[3]; 
criteria[0] = i => i % 2 == 0; 
criteria[1] = i => i % 3 == 0; 
criteria[2] = i => i % 5 == 0; 

И я хочу это:

Func<int, bool>[] predicates = new Func<int, bool>[3]; 
predicates[0] = i => i % 2 == 0; 
predicates[1] = i => i % 2 == 0 && i % 3 == 0; 
predicates[2] = i => i % 2 == 0 && i % 3 == 0 && i % 5 == 0; 

До сих пор у меня есть следующий код:

Expression<Func<int, bool>>[] results = new Expression<Func<int, bool>>[criteria.Length]; 

for (int i = 0; i < criteria.Length; i++) 
{ 
    results[i] = f => true; 
    for (int j = 0; j <= i; j++) 
    { 
     Expression<Func<int, bool>> expr = b => criteria[j](b); 
     var invokedExpr = Expression.Invoke(
      expr, 
      results[i].Parameters.Cast<Expression>()); 
     results[i] = Expression.Lambda<Func<int, bool>>(
      Expression.And(results[i].Body, invokedExpr), 
      results[i].Parameters); 
    } 
} 
var predicates = results.Select(e => e.Compile()).ToArray(); 

Console.WriteLine(predicates[0](6)); // Returns true 
Console.WriteLine(predicates[1](6)); // Returns false 
Console.WriteLine(predicates[2](6)); // Throws an IndexOutOfRangeException 

Кто-нибудь знает, что я Неправильно?

ответ

4

Это предположение, как я мало знаю об этой вещи, но это, кажется, это исправить:

Func<int, bool>[] criteria = new Func<int, bool>[3]; 
criteria[0] = i => i % 2 == 0; 
criteria[1] = i => i % 3 == 0; 
criteria[2] = i => i % 5 == 0; 
Expression<Func<int, bool>>[] results = new Expression<Func<int, bool>>[criteria.Length]; 
for (int i = 0; i < criteria.Length; i++) 
{ 
    results[i] = f => true; 
    for (int j = 0; j <= i; j++) 
    { 
     int ii = i; 
     int jj = j; 
     Expression<Func<int, bool>> expr = b => criteria[jj](b); 
     var invokedExpr = Expression.Invoke(expr, results[ii].Parameters.Cast<Expression>()); 
     results[ii] = Expression.Lambda<Func<int, bool>>(Expression.And(results[ii].Body, invokedExpr), results[ii].Parameters); 
    } 
} 
var predicates = results.Select(e => e.Compile()).ToArray(); 

Ключа введение «II» и «JJ» (может быть, только один с этими вопросами, Я не пробовал). Я думаю, что вы захватываете изменяемую переменную внутри лямбда, и, таким образом, когда вы, наконец, ссылаетесь на нее, вы видите более мутированное значение, а не исходное значение.

+0

Это зафиксировал его. Имело значение только jj. благодаря – 2008-10-02 02:49:04

5

Нет необходимости тянуть в выражениях ...

Func<int, bool>[] criteria = new Func<int, bool>[3]; 
    criteria[0] = i => i % 2 == 0; 
    criteria[1] = i => i % 3 == 0; 
    criteria[2] = i => i % 5 == 0; 

    Func<int, bool>[] predicates = new Func<int, bool>[3]; 

    predicates[0] = criteria[0]; 
    for (int i = 1; i < criteria.Length; i++) 
    { 
     //need j to be an unchanging int, one for each loop execution. 
     int j = i; 

     predicates[j] = x => predicates[j - 1](x) && criteria[j](x); 
    } 

    Console.WriteLine(predicates[0](6)); //True 
    Console.WriteLine(predicates[1](6)); //True 
    Console.WriteLine(predicates[2](6)); //False 
Смежные вопросы