Страницы

Поиск по вопросам

среда, 29 мая 2019 г.

Query Syntax против Method Syntax в LINQ

Во время написания LINQ-запроса чем необходимо руководствоваться при выборе стиля написания запроса? Использовать синтаксис запроса (Query Syntax) или метода (Method Syntax)? Что лучше использовать?
На мой взгляд методы удобнее и писать и читать, чего не скажешь про синтаксис запроса. В каких случаях необходимо использовать синтаксис запроса, а в каких синтаксис метода?
Очень хотелось бы узнать подробнее и с примерами, когда и чем лучше тот или иной подход написания запроса. Из этой статьи Query Syntax and Method Syntax in LINQ (C#) почему-то не все понял, да и есть места, где мое мнение отличается.


Ответ

Длинные и сложные запросы в синтаксисе методов могут стать нечитаемыми - особенно при частом использовании анонимных классов. Синтаксис же запроса скрывает эти анонимные классы от вас:
var q1 = trees.SelectMany(t => t.Leaves.Select(l => new { tree = t, leaf = l })) .OrderBy(x => x.leaf.color) .Select(x => x.tree.name);
Попробуйте переписать запрос выше без анонимного класса. А ведь в более длинных запросах могут появиться уже либо вложенные анонимные классы - либо постоянные копирования из одного анонимного класса в другой.
При использовании синтаксиса запроса многие анонимные классы успешно прячутся:
var q1 = from tree in trees from leaf in tree.Leaves order by leaf.Color select tree.Name;
Также в длинных запросах при использовании методов может быстро надоесть писать один и тот же префикс для каждого замыкания - в синтаксисе запроса же range variable определяется только 1 раз.
По этой причине в сложных запросах синтаксис запроса, как правило, предпочтительнее.

С другой стороны, некоторые вещи сделать в синтаксисе запроса просто невозможно.
К примеру, перегрузки методов, принимающие IEqualityComparer, могут быть вызваны только как методы.
Также синтаксис методов позволяет "накапливать" сложный запрос в переменной в зависимости от внешних условий - что полезно при обработке блоков фильтрации:
if (filters.Foo.HasValue) q = q.Where(x => x.Foo == filters.Foo);
if (filters.Bar != null) q = q.Where(x => x.Bar.Name == filters.Bar);

Комментариев нет:

Отправить комментарий