我尝试将自定义MethodInfo
传递给Expression.AndAlso
和OrElse
工厂方法(适用于&&
和||
分别是运营商)。这些运算符使用短路,这使得这很困难,但通常使用&
和|
运算符(以及true
和false
运算符)。但是,Expression.AndAlso/OrElse
的MSDN文档并未提及真或假运算符。
为了进行测试,我宣布了一种在两个整数中使用普通&
运算符的方法:
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
);
这会导致异常:
用户定义的运算符方法&#39;和&#39;对于运营商而言,还有其他&#39;必须有关联的布尔值True和False运算符。
奇怪的是,如果我使用具有true
和false
运算符的自定义结构,也会引发错误。如果struct重载&
运算符并且传入了该重载,我可以避免它,但是如果我传入一个不同的方法则不会。其他非短路运算符也可以使用自定义方法。
问题在于我不知道如何为true
和false
运算符传递方法。我首先想到我可以将它们组合为代理,但不同的方法有不兼容的签名。有没有办法传递这些方法?
更大的图片
我正在构建一个用于解释表达式的系统,以支持提前编译。它支持为AndAlso / OrElse运算符使用自定义方法,目前通过采用自定义Func<InterpretedExpression, InterpretedExpression, object>
(在表达式被解释而不是编译时起作用)。如果它导致问题(这可能是因为它没有可访问的true
和false
方法),这很容易被更改。
注意:我使用Visual Studio的C#Interactive窗口进行测试,但最终需要支持.NET 3.5(尽管有关新版本的信息仍然有用且值得赞赏)。
答案 0 :(得分:3)
问题在于我不知道如何为真假运算符传递方法。我首先想到我可以将它们组合为委托,但不同的方法具有不兼容的签名。有没有办法传递这些方法?
简短的回答是不,你不能。
查看reference source implementation(遗憾的是,它应该在文档中),看起来传递的方法有以下约束:
(1)它应该是带有签名的static
非通用方法
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
);
我想这限制了你所追求的更普遍的用法。