为什么我的具有多个参数的 LINQ 表达式无法编译?

Why is my LINQ Expression with multiple parameters not compiling?

我想扩展 LINQ 表达式 (DoSomething)

using LinqKit; // for System.Linq.Expressions.Expression<>.Invoke()

public class Expressions
{
  public static System.Linq.Expressions.Expression<
    System.Func<int, int, int, int, bool>>
      DoSomething =
        (a, b, c, d) => false;
}

public class ExpressionTester
{
  public ExpressionTester()
  {
    Expressions.DoSomething.Invoke(1, 2, 3, 4);
  }
}

有一个额外的参数,但它不编译:

public class Expressions
{
  public static System.Linq.Expressions.Expression<
    System.Func<int, int, int, int, int, bool>>
      DoSomething =
        (a, b, c, d, e) => false;
}

public class ExpressionTester
{
  public ExpressionTester()
  {
    Expressions.DoSomething.Invoke(1, 2, 3, 4, 5);
  }
}

The best overloaded method match for 'System.Linq.Expressions.Expression.Invoke(System.Linq.Expressions.Expression, params System.Linq.Expressions.Expression[])' has some invalid arguments
error CS1503: Argument 1: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 2: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 3: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 4: cannot convert from 'int' to 'System.Linq.Expressions.Expression'
error CS1503: Argument 5: cannot convert from 'int' to 'System.Linq.Expressions.Expression'

参数数量是否有未记录的限制?

:编辑

多亏一位未知作者的回答在 10 秒后删除了它的答案,我看到 LinqKit 是用 .NET 3.5 编译的,而这导致 System.Func<> 限制为 4 个参数。

:edit2

建议的 Compile().Invoke() 解决方法在所有与查询相关的情况下都不起作用(我需要)。因此,我从 LINQKit 项目创建了一个分支,并添加了一些代码以支持最多 16 个参数:

https://github.com/ViRuSTriNiTy/LINQKit/commit/bcca71978ef3fbb988d242463adfbc4e9cd42565

LinqKit 1.1.2 I've found on nuget (and on github) 最多支持四个参数为Invoke...

public static TResult Invoke<T1, T2, T3, T4, TResult>(this Expression<Func<T1, T2, T3, T4, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
    return expr.Compile()(arg1, arg2, arg3, arg4);
}

在有 4 个参数的基础上对 5 个参数做这个是微不足道的。

public static TResult Invoke<T1, T2, T3, T4, T5, TResult>(this Expression<Func<T1, T2, T3, T4, T5, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
    return expr.Compile()(arg1, arg2, arg3, arg4, arg5);
}

您可以直接调用 .Compile().Invoke()。此代码编译:

public class Expressions
{
    public static System.Linq.Expressions.Expression<
      System.Func<int, int, int, int, int, bool>>
        DoSomething =
          (a, b, c, d, e) => false;
}

public class ExpressionTester
{
    public ExpressionTester()
    {
        Expressions.DoSomething.Compile().Invoke(1, 2, 3, 4, 5);
    }
}

当您添加第五个参数时,您将绑定到与 LinqKit 中的参数不同的 Invoke:

public static TResult Invoke<T1, T2, T3, T4, TResult> (
    this Expression<Func<T1, T2, T3, T4, TResult>> expr, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
    return expr.Compile ().Invoke (arg1, arg2, arg3, arg4);
}

请注意,没有一个具有 5 个参数,因此您最终绑定到 Expression.Invoke,它采用 Expressions:

的参数数组
public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) {
    return Invoke(expression, (IEnumerable<Expression>)arguments);
}

幸运的是,您只需在表达式上调用 Compile() 将其转换为委托即可从 LinqKit 复制实现:

public class ExpressionTester
{
  public ExpressionTester()
  {
    Expressions.DoSomething.Compile().Invoke(1, 2, 3, 4, 5);
  }
}