写Li​​nq Where语句的更好方法

时间:2016-08-30 09:36:56

标签: c# linq

我对Linq查询中的一些多重过滤器感到困惑。

像这样:

var OrderList = (from o in db.Order
                 where ( o.OrderType == 1 && 
                 (( (o.Status & 1) != 0) || ((o.Status & 2) != 0)) )
                 || ( o.OrderType == 2 && 
                 (( (o.Status & 3) != 0) || ((o.Status & 4) != 0)) )
                 orderby o.OrderID descending
                 select new
                 {
                    Name = o.Name
                 }).ToList();

Linq中过滤看起来很丑,不易阅读。

有更好的方法来重写这个吗?

1 个答案:

答案 0 :(得分:4)

假设Status是数值类型(例如intuintlong等),并且没有&的自定义实现运算符&使用其操作数执行按位AND

因此((o.Status & 1) != 0) || ((o.Status & 2) != 0)(o.Status & 3) != 0相同。它仅测试是否设置了两个最低有效位中的至少一个。 (请注意3的位是0011)。

因此(o.Status & 3) != 0) || (o.Status & 4) != 0(o.Status & 7) != 0相同(7的位为0111)。

所以你可以简化这个条件:

 (o.OrderType == 1 && (o.Status & 3) != 0) ||
 (o.OrderType == 2 && (o.Status & 7) != 0)

但这只是一种简化...... 可读性位于读者的眼中。对enum字段使用Status可能是合适的:

[Flags]
public enum States
{
    FirstBit = 1, // use self-explaining names here
    SecondBit = 2,
    ThirdBit = 4
}

// condition
(o.OrderType == 1 && (o.Status.HasFlag(States.FirstBit) || o.Status.HasFlag(States.SecondBit)) ||
(o.OrderType == 2 && (o.Status.HasFlag(States.FirstBit) || o.Status.HasFlag(States.SecondBit) || o.Status.HasFlag(States.ThirdBit)))

这个更长,但如果名称是自我解释的话可能更具可读性。