Когда лямбда в методе расширения делает слишком много? - PullRequest
7 голосов
/ 08 октября 2010

Я понимаю, что это частично субъективно, но мне, как правило, любопытно мнение сообщества, и я не смог успешно найти существующий вопрос, который решает эту проблему.

Я нахожусь в несколько религиозных дебатах ссотрудник по конкретному оператору Select в запросе L2EF.

.Select(r =>
{
    r.foo.Bar = r.bar;
    r.foo.Bar.BarType = r.Alpha;
    if (r.barAddress != null)
    {
        r.foo.Bar.Address = r.barAddress;
        r.foo.Bar.Address.State = r.BarState;
    }
    if (r.baz != null)
    {
        r.foo.Bar.Baz = r.baz;
        if (r.bazAddress != null)
        {
            r.foo.Bar.Baz.Address = r.bazAddress;
            r.foo.Bar.Baz.Address.State = r.BazState;
        }
    }
    return r.foo;
})

Предостережения:

  • Это Linq-to-Entities
  • Это после работа в БД выполнена и возвращена
  • Входной параметр r является анонимным

Лично я считаю, что (а)предложение select не должно изменять значения, оно должно просто проецироваться.Его контраргумент в том, что он ничего не меняет, он просто следит за тем, чтобы все правильно инициализировалось в результате запроса к БД.Во-вторых, я думаю, что как только он начнет входить в блоки полного кода и операторы возврата, пора определить метод или даже Func<T, U> и не делать все это встроенным.Сложность здесь, опять же, ввод анонимный, поэтому тип должен быть определен.Но, тем не менее, мы все еще обсуждаем общий смысл, если не конкретный.

Итак, когда лямбда-выражение делает слишком много?Где вы рисуете нечеткую линию на песке?

Ответы [ 6 ]

2 голосов
/ 08 октября 2010

Мой первый инстинкт - согласиться с вами, прежде всего, в отношении размера и сложности.

Однако он используется в контексте, где он будет (или иногда) исполняется как-то иначе, чем.NET-код (особенно если он превращен в часть SQL-запроса), я стану гораздо более терпимым к нему.

Итак, вот где я рисую нечеткую линию, а также почему я снова ее перемещаю:)

1 голос
/ 08 октября 2010

Мне пришлось некоторое время смотреть на это, прежде чем я увидел, что меня беспокоит.

  1. Для этого требуется рефакторинг.

  2. Тот факт, что мне потребовалось много времени, чтобы прочитать намерение лямбды.

Я не уверен, что смогу согласиться с вашим определением работы Селекта, но я согласен, что чем короче лямбда, тем лучше. Разбейте его для повторного использования, если инициализация после выборки в дБ необходима так сильно.

1 голос
/ 08 октября 2010

Лично я не думаю, что это длинное лямбда-выражение. Я думаю, вы увидите намного более сложные и вложенные лямбды в будущем. Особенно с чем-то вроде Rx.

Что касается изменений состояния ... ну, здесь он просто инициализирует значения. Я был бы только обеспокоен, если бы он присваивал состояние некоторой переменной за пределами лямбды, но это все инициализация r, поэтому мне кажется, что это нормально.

1 голос
/ 08 октября 2010

Я также согласен, что Select () должен использоваться для проекции.Я бы предпочел использовать ключевое слово «let» для предварительной проверки, чтобы можно было сохранить чистоту проекции в Select ().Это позволит Select () обращаться к переменной (ам), установленным с помощью «let».

0 голосов
/ 10 октября 2010

Длина лямбды меня совсем не беспокоит. Но я бы согласился с чувством грязи, когда вы присваиваете значение в своем утверждении выбора. Я бы отнес фактор инициализации в оператор чуть ниже оператора select.

0 голосов
/ 08 октября 2010

Вы должны учитывать другие ваши альтернативы ... есть ли лучшее место, чтобы поместить эту логику. В любом случае, вы выполняете каждую сущность в LINQ или в цикле foreach, чтобы выполнить эту дополнительную работу ... Если вы не хотите преобразовать его в свой собственный метод расширения, я бы сказал, оставьте его, если он работает.

Визуально, это не так грязно, так что это плюс. Или вы можете видеть, покупает ли вам ключевое слово let (в основном подзапрос) что-нибудь еще.

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