Должен ли я использовать два предложения "where" или "&&" в моем запросе LINQ?

При написании запроса LINQ с несколькими "и" условиями следует написать одно предложение where, содержащее && или несколько предложений where, по одному для каждого условия?

static void Main(string[] args)
{
    var ints = new List<int>(Enumerable.Range(-10, 20));

    var positiveEvensA = from i in ints
                         where (i > 0) && ((i % 2) == 0)
                         select i;

    var positiveEvensB = from i in ints
                         where i > 0
                         where (i % 2) == 0
                         select i;

    System.Diagnostics.Debug.Assert(positiveEvensA.Count() == 
                                         positiveEvensB.Count());
}

Есть ли какая-либо разница, отличная от личных предпочтений или стиля кодирования (длинные строки, читаемость и т.д.) между позитивными EvensA и позитивными EvensB?

Одно из возможных различий, которое приходит на ум, заключается в том, что различные поставщики LINQ могут лучше справляться с несколькими where, а не с более сложным выражением; это правда?

Ответ 1

Я лично всегда бывал с && vs. two where clauses, когда это не делает утверждение непонятным.

В вашем случае это, вероятно, вообще не будет заметным, но при условии, что клаузулы 2 будут иметь влияние производительности, если у вас большая коллекция, и если вы используете все результаты этого запроса. Например, если вы вызываете .Count() в результатах или перебираете весь список, выполняется первое предложение where, создающее новый IEnumerable, который будет полностью перечислить со вторым делегатом.

Объединение двух предложений вместе приводит к тому, что запрос формирует один делегат, который запускается по мере перечисления коллекции. Это приводит к одному перечислению через коллекцию и одному вызову делегату каждый раз, когда возвращается результат.

Если вы разделите их, все изменится. В качестве первого предложения where, которое перечисляется через исходную коллекцию, появляется вторая, где перечисляется ее предложение. Это вызывает потенциально (наихудший случай), 2 полных перечисления через вашу коллекцию и 2 делегата, вызванных для каждого члена, что может означать, что это утверждение (теоретически) может потребовать 2x скорости выполнения.

Если вы решите использовать предложения 2 where, то размещение более ограничительного предложения сначала поможет совсем немного, так как предложение second where выполняется только на элементах, которые передают первый.

Теперь, в вашем случае, это не имеет значения. В большой коллекции это могло бы быть. Как общее правило, я иду за:

1) Считываемость и ремонтопригодность

2) Производительность

В этом случае я думаю, что оба варианта одинаково поддерживаются, поэтому я бы выбрал более эффективный вариант.

Ответ 2

Это в основном проблема личного стиля. Лично, пока предложение where помещается на одной строке, я группирую предложения.

Использование множественного where будет иметь тенденцию быть менее производительным, потому что это требует дополнительного вызова делегата для каждого элемента, который делает это так далеко. Однако это может быть незначительной проблемой и должно рассматриваться только в том случае, если профилировщик показывает, что это проблема.

Ответ 4

Как и другие, это более личное предпочтение. Мне нравится использование && поскольку он более читабельен и имитирует синтаксис других основных языков.