Лучший способ написать заявление Linq Where

Я запутался насчет нескольких фильтров 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 ответ

Решение

При условии, что Status тип числового значения (например, int или же uint или же long и т. д.) и не имеет собственной реализации & оператор, & выполняет побитовое И со своими операндами.

Так ((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)))

Это длиннее, но может быть более читабельным, если названия говорят сами за себя.

Другие вопросы по тегам