【问题标题】:Combine multiple LINQ expressions from an array组合数组中的多个 LINQ 表达式
【发布时间】:2008-10-02 02:19:22
【问题描述】:

我正在尝试像这样组合一个函数列表。

我有这个:

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

有谁知道我做错了什么?

【问题讨论】:

    标签: c# .net linq expression


    【解决方案1】:

    无需拉入表达式...

        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
    

    【讨论】:

      【解决方案2】:

      这是一个猜测,因为我对这些东西知之甚少,但这似乎可以解决它:

      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'的引入(可能只有一个重要,我没试过)。我认为您在 lambda 中捕获了一个可变变量,因此当您最终引用它时,您看到的是后来变异的值而不是原始值。

      【讨论】:

        猜你喜欢
        • 2018-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 1970-01-01
        相关资源
        最近更新 更多