Подтвердить что ты не робот

Когда это слишком много "лямбда-действий"?

Я часто нахожу себя использующим лямбды как своего рода "локальные функции", чтобы облегчить мою жизнь повторными операциями, такими как:

Func<string, string> GetText = (resource) => this.resourceManager.GetString(resource);
Func<float, object, string> FormatF1 = (f, o) => String.Format("{0:F1} {1}", f, o);
Func<float, object, string> FormatF2 = (f, o) => String.Format("{0:F2} {1}", f, o);

Вместо того, чтобы писать String.Format-вещь снова и снова, я могу с радостью сдуть FormatF2, например. и сэкономить время и когда мне нужно что-то изменить в отношении форматирования, только одно место для внесения изменений. Особенно, когда мне нужна функциональность только в данной функции, я очень неохотно превращаю их в настоящую функцию. В то время как лямбды выше были относительно небольшими... иногда у меня есть более крупные (например, предполагается добавить данные в таблицу для вывода на печать):

Action<string, string, string> AddSurfaceData = (resource, col, unit) => {
    renderTable.Cells[tableRowIndex, 0].Text = "\t" + this.GetText(resource);
    renderTable.Cells[tableRowIndex, 1].Text = FormatF2(paraHydReader.GetFloat(paraHydReader.GetOrdinal(col)), "");
    renderTable.Cells[tableRowIndex, 1].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Right;
    renderTable.Cells[tableRowIndex, 2].Text = " " + this.GetText(unit);
    renderTable.Cells[tableRowIndex, 2].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Left;
    ++tableRowIndex;
};

Опять же, мне это нужно часто, и все преимущества вышеприведенного тоже. Однако, как вы можете видеть, это довольно длинное выражение для лямбды.. вопрос: когда вы рисуете линию? Моя последняя лямбда слишком много? Какие другие способы (кроме использования реальных функций или попытки заполнить данные в контейнерах и их цикл) существуют, чтобы не писать один и тот же код снова и снова?

Заранее спасибо

Christian

4b9b3361

Ответ 1

Это то, что вы используете потенциально много раз в рамках метода, и только это внутри этого метода. Мне нравится эта идея. Сделайте это, если это не делает ваш код трудно читать. Я бы сказал, что вам следует пересмотреть, если вам трудно понять, что является содержанием лямбда-функции, чем то, что является реальным содержанием метода. В этом случае может быть более чистым вытащить его в отдельном частном методе.

В конце концов, это действительно вопрос вкуса...

Ответ 2

Я согласен с благоговением: для малогабаритного повторного использования внутри метода (или даже класса) это идеально. Как и примеры string.Format. Я использую это довольно часто. Это в основном то же самое, что использование локальной переменной для промежуточного значения, которое вы используете более одного раза, но затем для кода.

Ваш второй пример, похоже, немного подталкивает его. Почему-то это дает мне ощущение, что частный метод AddSurfaceData (возможно, статический, в зависимости от его использования?) Будет лучше подходит. Это, конечно, вне контекста, который у вас есть, поэтому используйте свое собственное мнение.

Ответ 3

Лямбда-метод - анонимный метод.

Это означает, что вы не должны указывать его имя.

Если вы это делаете (в вашем случае вы назначаете имя своей ссылкой), это просто еще один способ объявить функцию.

У С# уже есть способ объявить функции, и это не лямбда-путь, который был добавлен однозначно передавать функции через параметры и возвращает их как возвращаемые значения.

Подумайте, например, в javascript:

function f(var1,var2,...,varX)
{
    some code
}

или

var f = function() {
    some code    
}

Разный синтаксис (почти) то же самое.

Для получения дополнительной информации о том, почему это не одно и то же: Javascript: var functionName = function() {} vs function functionName() {}

Другой пример: в Haskell Вы можете определить две функции:

 function1 :: Int -> Int
 function1 x = x + 2

или

 function2 :: Int -> Int
 function2 = \x -> x + 2

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

С# 3.5, как Javascript, имеет много функциональных влияний. Некоторые из них должны быть разумно использованы, ИМХО.

Кто-то сказал, что локальные лямбда-функции с присваиванием в ссылке являются хорошей заменой для метода, определенного в другом методе, аналогичном предложению "let" или "where" в Haskell.

Я говорю "похоже", потому что у twos есть очень разные семантики, например, в Haskell я могу использовать имя функции, которое еще не объявлено, и определить позже с "where", а в С#, с назначением функции/ссылки я не может этого сделать.

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

Ответ 4

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

Ответ 5

+1 на nikie re DRY является хорошим вообще.

Я бы не использовал PascalCase для них.

Будьте осторожны, хотя в большинстве случаев материал, который у вас есть, - это всего лишь метод извлечения в одежде или потенциальный помощник или функция расширения. например, GetText является методом и FormatF*, вероятно, является вспомогательным методом...

Ответ 6

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

Это короткие, которые побудят ваших коллег расследовать преимущества добровольной институционализации. Пожалуйста, объявляйте какую-то константу, чтобы держать вашу строку формата и использовать "эту String.Format-вещь снова и снова". Как программист на С#, я знаю, что это делает, не глядя в другое место для домашних функций. Таким образом, когда мне нужно знать, как будет выглядеть форматированная строка, я могу просто изучить константу.

Ответ 7

Я согласен с volothamp в целом, но кроме того...

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

String.Format(this.resourceManager.GetString("BasicFormat"), f, o);
String.Format(this.resourceManager.GetString("AdvancedFormat"), f, o);

И ваш второй пример - это просто другой способ объявить функцию. Я не вижу полезной пользы от объявления вспомогательного метода. И объявление вспомогательного метода будет более понятным большинству кодеров.

Ответ 8

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

Я бы не использовал его для замены string.format.