Использование методов расширения в сравнении с лямбда-выражением в c # - PullRequest
1 голос
/ 02 сентября 2011

Предположим, у меня есть метод расширения

    public static IEnumerable<Product> Filter(
    this IEnumerable<Product> productEnum,
    Func<Product, bool> selectorParam)
    {
        return productEnum.Where(selectorParam);
    }

, который я называю так

    Func<Product, bool> languageFilter = prod => prod.Language == lang;

, который, если я не ошибаюсь, функционально совпадает с

var products = Products.Where(q => q.Language == parameter);

Я пытаюсь понять, когда можно использовать метод расширения согласно первому примеру, а когда использовать синтаксис linq.

Ответы [ 3 ]

2 голосов
/ 02 сентября 2011

Я думаю, что вы путаете некоторую терминологию. Метод Filter, который вы показываете, является методом расширения (обозначается как таковое ключевым словом this в списке параметров. То, что вы называете "синтаксисом linq", на самом деле является лямбда-выражением.

Все методы LINQ реализованы как методы расширения и поддерживают два "стиля" вызова:

  1. На самом деле вызовите метод расширения напрямую, как если бы он был частью расширяемого типа. Это то, что вы показываете, когда называете это productEnum.Where(selectorParam).

  2. Использование более похожего на SQL синтаксиса, называемого синтаксисом запроса LINQ. Имейте в виду, что этот SQL-подобный синтаксис транслируется компилятором для фактического вызова методов расширения.

Когда вы определяете Func<Product, bool> languageFilter = prod => prod.Language == lang;, вы фактически определяете лямбда-выражение и присваиваете его переменной (languageFilter) типа Func<Product, bool>. Оператор Products.Where(q => q.Language == parameter); точно такой же, за исключением того, что вместо захвата лямбда-выражения в переменной вы просто передаете его в метод расширения.

Для вашего примера, чтобы получить тот же результат, используя синтаксис запроса LINQ, вы бы написали его аналогично

from p in Products
where p.Language == parameter

(при условии, что параметр определен в другом месте)

1 голос
/ 02 сентября 2011

Я думаю, если в фреймворке уже есть метод расширения, чтобы делать то, что вы хотите, используйте это.Метод «Где» также является методом расширения, но не тот, который вы написали.Мое обоснование заключается в том, что «эти умные парни из Microsoft, вероятно, сделали это лучше, чем я когда-либо».

1 голос
/ 02 сентября 2011

Внутренне синтаксис linq разбит на метод расширения, поэтому функционально никакой разницы нет.

В вашем случае, когда у вас есть метод расширения фильтра, возможно, не имеет смысла использовать первую форму (которая, я полагаю, является неполной в вашем вопросе, случайно). Тем не менее, давайте предположим, что в вашем методе Filter есть какая-то обычно используемая логика, которую вы не хотите повторять в каждом случае предложения where. В этом случае имеет смысл создать собственный метод расширения, чтобы вы могли повторно использовать эту логику.

Например, предположим, что мы работаем только с продуктами, срок действия которых не истек (при условии, что ваш объект Product имеет свойство isExpired). Поскольку вы, скорее всего, будете фильтровать эти не истекшие продукты далее с несколькими значениями selectorParam, вы можете просто использовать:

public static IEnumerable<Product> Filter(
    this IEnumerable<Product> productEnum,
    Func<Product, bool> selectorParam)
    {
        return productEnum.Where(x => !x.IsExpired).Where(selectorParam);
    }

Так что вместо звонка products.Where(x => !x.IsExpired).Where(q => q.Language == parameter) или products.Where(x => !x.IsExpired).Where(q => q.Price > parameter)

Вы можете просто использовать:
products.Filter(q => q.Language == parameter) и products.Filter(q => q.Price > parameter) соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...