简体   繁体   English

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

[英]Linq expression for comparing two enum values

I'm doing some expression building in my app, which is working most of the time. 我正在我的应用程序中构建一些表达式,这在大多数情况下都在工作。 But when I try to do comparative operations on an enum value, I hit trouble. 但是当我尝试对枚举值进行比较操作时,我遇到了麻烦。 For example: 例如:

expr = Expression.GreaterThanOrEqual(memberExpression, constExpression);

This works fine until memberExpression and constExpression are of type MyEnum ; 这样可以正常工作,直到memberExpressionconstExpression的类型为MyEnum ; this throws a runtime error: 这会引发运行时错误:

The binary operator GreaterThanOrEqual is not defined for the types 'MyNamespace.MyEnum' and 'MyNamespace.MyEnum'. 没有为类型'MyNamespace.MyEnum'和'MyNamespace.MyEnum'定义二元运算符GreaterThanOrEqual。

I could get around it some other place by converting the enum values to integers, but that seems wrong, somehow. 我可以通过将枚举值转换为整数来绕过其他地方,但这似乎是错误的,不知何故。 If I can do a comparative operation between MyEnum values in C#, then why doesn't the Expression builder allow it? 如果我可以在C#中的MyEnum值之间进行比较操作,那么为什么Expression构建器不允许它呢?

I could get around it some other place by converting the enum values to integers, but that seems wrong, somehow. 我可以通过将枚举值转换为整数来绕过其他地方,但这似乎是错误的,不知何故。

It shouldn't feel wrong. 它不应该感到错误。 That's what the compiler itself does, after all -- it either substitutes enum values for their corresponding numeric values (when the enum values are known at compile time) or it generates code that performs the necessary casts at runtime. 毕竟,这就是编译器本身所做的事情 - 它要么将枚举值替换为相应的数值(当枚举值在编译时已知),要么生成在运行时执行必要强制转换的代码。 Note that these casts are not necessarily to int but rather to the backing type of the enum in question. 请注意,这些强制转换不一定是int ,而是有问题的枚举的支持类型。

If I can do a comparative operation between MyEnum values in C#, then why doesn't the Expression builder allow it? 如果我可以在C#中的MyEnum值之间进行比较操作,那么为什么Expression构建器不允许它呢?

The expression tree you are building looks like it matches what happens in C# code, but in reality it doesn't -- precisely because of what the compiler does behind the scenes as mentioned above. 您正在构建的表达式树看起来与C#代码中发生的情况相匹配,但实际上并非如此 - 正是因为编译器在幕后所做的事情如上所述。

It is true there is no technical reason that Expression.GreaterThanOrEqual and friends cannot examine their arguments and generate the exact same expression tree that corresponds to what the compiler would do. 确实没有技术上的原因, Expression.GreaterThanOrEqual和朋友不能检查他们的参数并生成与编译器所做的完全相同的表达式树。 For example, if you pass in two ConstantExpression s with Type equal to MyEnum the method could use reflection to determine the numeric values that correspond to its arguments and behave as if you had passed in constant expressions of that type instead of throwing. 例如,如果传入两个Type等于MyEnumConstantExpressionMyEnum该方法可以使用反射来确定与其参数对应的数值,并且就像传入该类型的常量表达式而不是抛出一样。 It could also handle the general case (non-constant subexpressions) as well. 它也可以处理一般情况(非常数子表达式)。

However, doing so would mean that the WYSIWYG property of expression trees is lost: you would think that you are generating an expression tree X while in reality you would be generating a different expression tree Y. 但是,这样做意味着表达式树的WYSIWYG属性丢失:您会认为您正在生成表达式树X,而实际上您将生成不同的表达式树Y.

That might be perfectly desirable -- and you can certainly write methods of your own that do this -- but it is probably not a good idea as the default behavior (in general the design of C# shuns the DWIM mentality), and/or would not justify the cost of development. 这可能是完全可取的 - 你当然可以编写自己的方法来做到这一点 - 但它可能不是一个好主意,因为默认行为(通常C#的设计避免DWIM心态),和/或不能证明发展成本。 Keep in mind that there are a great many places where the compiler does the heavy lifting out of sight so accommodating just a subset of these scenarios would be arbitrary, while accommodating all of them would probably be prohibitive. 请记住,有很多地方编译器可以解除繁重的工作,因此只容纳这些场景的一部分是任意的,而容纳所有这些场景可能会让人望而却步。 It would be interesting to see if the availability of Roslyn changes this evaluation. 看看Roslyn的可用性是否会改变这一评估将会很有趣。

I eventually did not convert to integers. 我最终没有转换为整数。

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM