我正在尝试传递自定义 MethodInfo
到Expression.AndAlso
和OrElse
工厂方法(分别用于 &&
和 ||
运算符)。这些运算符使用短路,这使得这变得很困难,但通常 &
和|
使用运算符(以及 true
和 false
运算符)。但是,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>
(其工作原理是表达式被解释而不是编译)。如果它导致问题(这可能是由于它没有可访问的 true
和 false
方法),则可以很容易地更改它。
注意:我使用 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) 方法的声明类型必须定义运算符true
和false
。
由于运算符 true
和 false
要求参数类型与声明类型相同,因此与 (1) 结合确实限制了对类/结构的使用T
声明静态方法以及 true
和 false
运算符。
换句话说,具有按位 &
/|
运算符语义的方法,而无需实际重载这些运算符。
所以它只能用于这样的类型:
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/