Building 'flat' rather than 'tree' LINQ expressions

浪子不回头ぞ 提交于 2019-12-05 11:26:36

You need to modify the generation so that it builds a ballanced tree instead of a sequence of ORs where the left sub-tree is a single expression and the right sub-tree contains all remaining elements. Graphically:

 Your code               Better
 ---------              --------
    OR                     OR
 #1    OR              OR      OR
     #2  OR          #1  #2  #3  #4
       #3  #4

As you can see, even in this simple case, the better approach is not as deeply (recursively nested). The code to generate the better expression tree can be written as a recursive method in C#:

Expression GenerateTree(List<Expression> exprs, int start, int end) {
  // End of the recursive processing - return single element
  if (start == end) return exprs[start];

  // Split the list between two parts of (roughly the same size)
  var mid = start + (end - start)/2;
  // Process the two parts recursively and join them using OR
  var left = GenerateTree(exprs, start, mid);
  var right = GenerateTree(exprs, mid+1, end);
  return Expression.Or(left, right);
}

// Then call it like this:
var equalsList = equals.ToList();
var body = GenerateTree(equalsList, 0, equalsList.Length);

I didn't try the code, so there may be some minor mistakes, but it should show the idea.

If this is truly LINQ to Objects as per your tags, why are you building expression trees at all? You can use delegates very easily, and they won't have a recursion limit.

However, more to the point: if you just want to see whether an ID is in some particular collection, why aren't you using something like:

var query = from item in source
            where idCollection.Contains(item.Id)
            ...
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!