2017-04-16 64 views
2

我想要在自定义MethodInfoExpression.AndAlsoOrElse工厂方法(这是用于&&||运营商,分别)通过。这些运营商使用短路,这使得这很困难,但通常使用&|运营商(以及truefalse运营商)。但是,Expression.AndAlso/OrElse的MSDN文档没有提及真假操作符。构建AndAlso/OrElse运算LINQ表达与自定义的方法

为了测试,我已经宣布对两个整数使用普通&操作的方法:

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 
); 

这导致异常:

用户定义的操作方法“与”操作员“AndAlso”必须具有相关联的布尔真和假的运营商。

奇怪的是,如果我使用具有truefalse运营商定制的结构中的错误也被抛出。我可以避免它,如果结构重载&运算符,我传入该重载,但不是如果我传入一个不同的方法。尽管如此,其他非短路操作符仍然可以使用自定义方法。

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


的大局观

我建立一个系统,用于解释表达式支持名列前茅的时间编译。它支持使用AndAlso/OrElse运算符的自定义方法,目前通过自定义Func<InterpretedExpression, InterpretedExpression, object>(其工作原因是表达式被解释而不是编译)。如果它导致问题很容易被改变(这可能是由于它没有可访问的方法truefalse)。


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

回答

3

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

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

望着reference source implementation(不幸的是,它确实应该在文档中),看起来像传递方法有以下限制:

(1)这应该是一个static非通用方法与签名

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 
); 

此我想限制更普遍的用法你之后。

相关问题