Почему Action / Func лучше, чем обычный метод in.Net?

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

почему это лучше сделать так:

Action<FormView,String> hideControl = (form,name) => {
    var button = form.GetControl<Button>(name);
    if (button != null)
        button.Visible = false;
}

чем:

public static void HideControl<T>(this FormView form, string name) where T : Control
{
    var button = form.GetControl<Button>(name);
    if (button != null)
        button.Visible = false;
}

?

может ли кто-нибудь дать мне твердые конкретные аргументы/примеры?

5 ответов


есть две стороны вашего вопроса: стиль и производительность.

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

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

любой инструмент имеет соответствующее и чрезмерного использования. Целесообразно использовать Action или Func для параметра обратного вызова, когда вы хотите передать процедуру обратного вызова в функцию. Использование Action или Func в качестве замены для объявления функций в целом является неправильным, ММО.


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

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

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

это гораздо более читабельно и ремонтопригодный:

var myQuery = Customers.Where(x => x.ID == 3).First();

чем альтернатива:

public bool FilterByID3(Customer cust)
{
  return cust.ID == 3;
}

    var myQuery = Customers.Where(FilterByID3).First();

в большинстве других случаев гораздо более читабельно/ремонтопригодно использовать функции.


почему это лучше сделать

Это не лучше. В этом случае я не вижу никаких преимуществ в этом, а не в написании реального метода. А если и ты не можешь, то я не понимаю, почему ты так уверен, что так лучше.

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

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


в целом я согласен с другими ответчиками: слепо заменяя определения функций на Action/Func это не хорошо. Action и Func не на будущее .Сеть. Они a инструмент, который очень полезен, но, как и любой инструмент, может быть использован неправильно.

так что если вы склонны писать такой код

class SomeClass {
    Action<...> a1 = (..) => {};
    Func<...> f1 = (..) => {};
    Action<...> a2 = (..) => {};
    ...
}

это, конечно, не хорошо.

если вы делаете это много:

  void SomeMethod()
  {
      Action<..> a = (..) => {};
      ...
      a();
  }

тогда это на самом деле хороший способ инкапсуляции небольшого вспомогательного метода без загрязнения класса.

чтобы аргументировать свой конкретный случай: Если hideControl используется только в очень конкретном случае, предпочтительным будет метод частного помощника. Если это требуется для много FormViews метод расширения имеет больше смысла. Методы расширения также являются инструментом, который может использоваться неправильно, поскольку это может привести к загрязнению открытого интерфейса для класса. Хотя вы можете ограничить его через использование пространство имен.

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


плюсы

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

минусы

  • читаемость уменьшается, на мой взгляд, из-за избыточного отступа (я не поклонник).
  • отладка становится немного сложнее, потому что ваш стек вызовов-это менее интуитивно, особенно когда у вас есть несколько Func/Actionс определенными.

вам придется прийти к минусам в вашей среде.

меня интересует ваш аргумент "более современная практика кодирования". Просто потому что ты!--36-- > can сделать это как можно больше, не значит, что вы должны.