Синтаксис методов расширения против синтаксиса запросов - PullRequest
64 голосов
/ 11 ноября 2008

Я пытаюсь понять, есть ли время использовать стандартные ключевые слова linq или методы расширения linq с лямбда-выражениями. Кажется, они делают одно и то же, просто пишутся по-разному. Это чисто вопрос стиля?

var query = from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p;

// or with extension methods:
var query = Products
    .Where(p => p.Name.Contains("foo"))
    .OrderBy(p => p.Name);

Они очень похожи, второй пример немного более краткий, но, возможно, менее выразительный, если вы не знаете, что делает =>.

Помимо написания краткого кода, есть ли другие преимущества использования методов расширения по сравнению с синтаксисом LINQ?

Ответы [ 7 ]

33 голосов
/ 12 ноября 2008

Честно говоря, иногда это может быть ситуативным, когда вы начинаете использовать Funcs и Actions. Скажем, вы используете эти три функции:

  Func<DataClasses.User, String> userName = user => user.UserName;
  Func<DataClasses.User, Boolean> userIDOverTen = user => user.UserID < 10;
  Func<DataClasses.User, Boolean> userIDUnderTen = user => user.UserID > 10;

Как видите, первое заменяет выражение lamdba, чтобы получить имя пользователя, второе заменяет выражение lamdba, используемое для проверки, если идентификатор меньше 10, и давайте посмотрим правде в глаза, третье должно быть довольно легко понять. Теперь.

ПРИМЕЧАНИЕ. Это глупый пример, но он работает.

  var userList = 
    from user in userList
    where userIDOverTen(user)
    select userName;

Versus

  var otherList =
    userList
    .Where(IDIsBelowNumber)
    .Select(userName)

В этом примере второй является немного менее многословным, поскольку метод расширения может в полной мере использовать Func, но выражение Linq не может, так как он ищет только Boolean, а не Func, который возвращает Boolean. Однако здесь может быть лучше использовать язык выражений. Скажем, у вас уже есть метод, который принимает больше, чем просто пользователь:

  private Boolean IDIsBelowNumber(DataClasses.User user, 
          Int32 someNumber, Boolean doSomething)
  {
    return user.UserID < someNumber;
  }

Примечание: doSomething существует только потому, что метод where расширения подходит для метода, который принимает пользователя и целое число и возвращает логическое значение. Раздражает этот пример.

Теперь, если вы посмотрите на запрос Linq:

  var completeList =
     from user in userList
     where IDIsBelowNumber(user, 10, true)
     select userName;

Ты хорош для этого. Теперь метод расширения:

  var otherList =
    userList
    .Where(IDIsBelowNumber????)
    .Select(userName)

Без лямбда-выражения я действительно не могу вызвать этот метод. Итак, теперь мне нужно создать метод, который создает Func на основе исходного вызова метода.

   private Func<DataClasses.User, Boolean> IDIsBelowNumberFunc(Int32 number)
   {
      return user => IDIsBelowNumber(user, number, true);
   }

А затем подключите его:

  var otherList =
     userList
     .Where(IDIsBelowNumberFunc(10))
     .Select(userName)

Как видите, иногда может быть проще использовать подход с использованием запросов.

24 голосов
/ 11 ноября 2008

Одним из преимуществ использования методов расширения LINQ ( запросов на основе методов ) является то, что вы можете определять собственные методы расширения, и он все равно будет читать нормально.

С другой стороны, при использовании выражения запроса LINQ пользовательский метод расширения отсутствует в списке ключевых слов. Это будет выглядеть немного странно в сочетании с другими ключевыми словами.

Пример

Я использую пользовательский метод расширения под названием Into, который просто принимает строку:

Пример с запросом

var query = (from p in Products
    where p.Name.Contains("foo")
    orderby c.Name
    select p).Into("MyTable");

Пример с методами расширения

var query = Products
                   .Where(p => p.Name.Contains("foo"))
                   .OrderBy(p => p.Name)
                   .Into("MyTable");

По моему мнению, последний, использующий запрос на основе метода , лучше читает, когда у вас есть собственные методы расширения.

14 голосов
/ 01 декабря 2010

Я думаю, что это хорошая идея - не использовать их вместе, выбрать один и придерживаться его.

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

Я нахожу синтаксис «Методы расширения» более соответствующим остальному моему коду. Я делаю мой SQL в SQL. Также очень легко построить свое выражение, просто добавив все поверх друг друга с помощью методов расширения.

Только мои два цента.

Поскольку я пока не могу комментировать, я хочу сделать здесь один ответ на инструмент программирования: Зачем делать совершенно новый метод для последнего примера? Разве вы не можете просто использовать:

.Where(user => IDIsBelowNumber(user, 10, true))

6 голосов
/ 11 ноября 2008

Они компилируются одинаково и эквивалентны. Лично я предпочитаю лямбда (расширение) методы для большинства вещей, только используя операторы (стандартные), если я делаю LINQ to SQL или иным образом пытаюсь эмулировать SQL. Я считаю, что лямбда-методы лучше работают с кодом, тогда как операторы визуально отвлекают.

4 голосов
/ 12 ноября 2008

Я предпочитаю синтаксис метода расширения, когда использую методы Linq, которые не имеют эквивалентного синтаксиса запроса, например FirstOrDefault () или тому подобное.

0 голосов
/ 09 января 2018

Одним из преимуществ методов расширения / выражений lynda являются дополнительные операторы, такие как Skip and Take. Например, если вы создаете метод разбиения на страницы, возможность пропустить первые 10 записей и взять следующие 10 легко реализовать.

0 голосов
/ 06 марта 2014

Мне нравится использовать синтаксис запроса, когда это действительно запрос, то есть ленивое выражение, которое оценивает по требованию.

Метод, который выглядит как обычный вызов метода (синтаксис метода или лямбда-синтаксис) не выглядит достаточно ленивым, поэтому я использую его как соглашение Например,

var query = from p in Products
            where p.Name.Contains("foo")
            orderby p.Name
            select p;

var result = query.ToList(); //extension method syntax

Если это не запрос, мне нравится свободный стиль, который мне кажется совместимым с другими нетерпеливо выполняемыми вызовами.

var nonQuery = Products.Where(p => p.Name.Contains("foo"))
                       .OrderBy(p => p.Name)
                       .ToList();

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

...