c# - 使用自定义方法构造 AndAlso/OrElse LINQ 表达式

标签 c# .net linq expression-trees

我正在尝试传递自定义 MethodInfoExpression.AndAlsoOrElse工厂方法(分别用于 &&|| 运算符)。这些运算符使用短路,这使得这变得很困难,但通常 &|使用运算符(以及 truefalse 运算符)。但是,Expression.AndAlso/OrElse 的 MSDN 文档没有提及 true 或 false 运算符。

为了测试,我声明了一个使用普通 & 的方法。两个整数上的运算符:

public static int And(int a, int b) {
    return a & b;
}

请注意,返回类型必须为 int而不是bool以避免异常。
然后我构建表达式:

var expr = Expression.AndAlso(
    Expression.Constant(0),
    Expression.Constant(5),
    new Func<int, int, int>(And).Method
);

这会导致异常:

The user-defined operator method 'And' for operator 'AndAlso' must have associated boolean True and False operators.

奇怪的是,如果我使用具有 true 的自定义结构,也会引发错误。和false运营商。如果结构重载 & 我可以避免它运算符和我传递该重载,但如果我传递不同的方法则不会。不过,其他非短路运算符使用自定义方法。

问题是我不知道如何传递 true 的方法和false我首先想到我可以将它们组合为委托(delegate),但不同的方法具有不兼容的签名。有什么办法可以传入这些方法吗?


大局观

我正在构建一个用于解释表达式的系统,以支持提前编译。它支持对 AndAlso/OrElse 运算符使用自定义方法,当前通过采用自定义 Func<InterpretedExpression, InterpretedExpression, object> (其工作原理是表达式被解释而不是编译)。如果它导致问题(这可能是由于它没有可访问的 truefalse 方法),则可以很容易地更改它。


注意:我使用 Visual Studio 的 C# 交互窗口进行测试,但最终需要支持 .NET 3.5(尽管较新版本的信息仍然很有帮助和赞赏)。

最佳答案

The problem is that I don't know how to pass methods for the true and false operators in. I first thought I could maybe combine them as delegates, but the different methods have incompatible signatures. Is there any way to pass these methods in?

简短的回答是否定的,你不能。

查看reference source implementation (不幸的是,它确实应该在文档中),看起来传递的方法具有以下约束:

(1) 它应该是一个带有签名的静态非通用方法

static T Method(T arg0, T arg1);

其中 T 不能是开放泛型类型

(2) 方法的声明类型必须定义运算符truefalse

由于运算符 truefalse 要求参数类型与声明类型相同,因此与 (1) 结合确实限制了对类/结构的使用T 声明静态方法以及 truefalse 运算符。

换句话说,具有按位 &/| 运算符语义的方法,而无需实际重载这些运算符。

所以它只能用于这样的类型:

public struct IntWrapper
{
    public readonly int Value;
    public IntWrapper(int value) { Value = value; }
    public static IntWrapper And(IntWrapper a, IntWrapper b) { return new IntWrapper(a.Value & b.Value); }
    public static bool operator true(IntWrapper x) { return x.Value != 0; }
    public static bool operator false(IntWrapper x) { return x.Value == 0; }
}

用法:

var expr = Expression.AndAlso(
    Expression.Constant(new IntWrapper(0)),
    Expression.Constant(new IntWrapper(5)),
    new Func<IntWrapper, IntWrapper, IntWrapper>(IntWrapper.And).Method
);

我想这限制了您所追求的更一般的用法。

关于c# - 使用自定义方法构造 AndAlso/OrElse LINQ 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43434080/

相关文章:

c# - 如何使用 LINQ 从列表列表输出由单个索引构造的整数列表?

linq - 在函数中使用 T 匿名参数验证 Linq 对象的类型、属性

c# - 检查 UI 元素/RectTransform 是否重叠

.net - .NET 程序集中的 SVN 修订版,不带 CC.NET

c# - (C#) 我应该在计算中防范无穷大/-无穷大吗? IE。抛出溢出异常?

c# - 使用带有 <%@ Register %> 的空 TagPrefix

c# - 在 Linq 表达式主体中如何使用变量的值而不是对它的引用?

c# - 如何配置对 YouTube 凭据进行身份验证的网站以供控制台应用程序使用?

C# - 自动添加 'X' 个按钮,一个接一个。

c# - 无法从 C# 选择全局临时表 (##TempTable)