Linq表达式用于比较两个枚举值

时间:2014-03-13 11:14:47

标签: c# linq-to-entities

我正在我的应用程序中构建一些表达式,这在大多数时间都在工作。但是当我尝试对枚举值进行比较操作时,我遇到了麻烦。例如:

expr = Expression.GreaterThanOrEqual(memberExpression, constExpression);

memberExpressionconstExpression类型MyEnum之前,此工作正常;这会引发运行时错误:

  

没有为类型'MyNamespace.MyEnum'和'MyNamespace.MyEnum'定义二元运算符GreaterThanOrEqual。

我可以通过将枚举值转换为整数来绕过其他地方,但这似乎是错误的,不知何故。如果我可以在C#中的MyEnum值之间进行比较操作,那么为什么“表达式”构建器不允许它呢?

2 个答案:

答案 0 :(得分:3)

  

我可以通过转换枚举值来绕过其他地方   整数,但这似乎是错误的,不知何故。

不应该感到错误。这毕竟是编译器本身所做的 - 它要么将枚举值替换为相应的数值(当枚举值在编译时已知),要么生成在运行时执行必要强制转换的代码。请注意,这些强制转换不一定是int,而是有问题的枚举的支持类型。

  

如果我可以在C#中的MyEnum值之间进行比较操作,那么   为什么Expression构建器不允许它?

您正在构建的表达式树看起来与C#代码中发生的情况相匹配,但实际上它并不是 - 正是因为编译器在幕后工作所做的如上所述。

确实没有技术原因导致Expression.GreaterThanOrEqual和朋友无法检查他们的参数并生成与编译器所做的完全相同的表达式树。例如,如果传入两个ConstantExpressionType等于MyEnum,则该方法可以使用反射来确定与其参数对应的数值,并且表现得就像传入了该类型的常量表达式而不是抛出。它也可以处理一般情况(非常数子表达式)。

然而,这样做意味着表达式树的WYSIWYG属性丢失:您会认为您正在生成表达式树X,而实际上您将生成不同的表达式树Y.

这可能是完全可取的 - 你当然可以编写自己的方法来做到这一点 - 但它可能不是一个好主意,因为默认行为(一般来说,C#的设计避免了DWIM心态),和/或不能证明发展成本。请记住,有很多地方编译器可以解除繁重的工作,因此只容纳这些场景的一部分是任意的,而容纳所有这些场景可能会让人望而却步。看看Roslyn的可用性是否会改变此评估会很有趣。

答案 1 :(得分:0)

我最终没有转换为整数。

private static void Example(string value, Type type, ParameterExpression pe, string propertyName)
{
    Expression whereValue = null;
    if (type.IsEnumOrNullableEnum())
    {
        whereValue = Expression.Constant(Enum.Parse(type, value));
    }
    Expression propExp = Expression.Property(pe, propertyName);
    Expression ruleExpression = Expression.Equal(propExp, whereValue);//results in: item.MyEnum = A
}