4

В c# 7.0 появились вложенные функции. Собственно вопрос, а когда использование данного синтаксиса оправданно? Я понимаю, что это синтаксический сахар, но ИМХО и без них раньше жилось хорошо. Подчеркнуть, что данная функция вызывается в одном месте? Ну не знаю...

iluxa1810
  • 24,899
  • 1
    Никто не запрещает плодить приватные функции, которые нужны в одном месте и потом путаться в них. Фломастеры это все. – vitidev Jun 20 '17 at 17:50
  • @vitidev, ну не знаю. По мне так и во вложенных функциях путаться можно. Тем более вложенность может быть любой. Еще я заметил, то ли баг, то ли фича, что нельзя в локальной функции в дебаггере посмотреть переменную из внешний функции, которая передавалась не в виде параметра. – iluxa1810 Jun 20 '17 at 18:11
  • Теперь вы можете в код-гольфе написать типа void w<T>(T t)=>Console.Write(t); и если вывод в консоль используется хотя бы в нескольких местах - выиграть пару символов: w("Hello"); ))) – Андрей NOP Jun 21 '17 at 03:19
  • Это очередное, что в C# тянут из функционального подхода, так что если вам интересные "новые" возможности C#, то я просто советую вам познакомиться с F# где все это было реализовано намного раньше и во многом лучше. –  Jun 21 '17 at 04:30
  • Если вы все-таки заинтересуетесь F#, то заходите в F#-чат комнату - не стесняйтесь спрашивать если будут вопросы, в любом случае буду рад вас видеть. –  Jun 21 '17 at 04:32
  • 2
    @FoggyFinder: А ещё раньше это было реализовано в насквозь процедурном Паскале. – VladD Jun 21 '17 at 07:04

1 Answers1

3

Подчеркнуть, что данная функция вызывается в одном месте?

Не обязательно. Она может выполняться и много раз в методе, в котором она вложена. Просто сейчас такие "локально выполняемые" функции можно не выносить в класс. Как следствие - класс будет чище и читабельней.

К слову, вложенная функция имеет доступ к локальным переменным метода:

var number = 23;
void DoAction()
{
    Console.WriteLine(number); // 23
}

DoAction();

Так же нашел пользу использования вложенных функций в подписках на события. Давайте приведу пример, как это выглядело раньше:

EventHandler createdEventHandler = null;
createdEventHandler += (sender, e) =>
{
    something.Created -= createdEventHandler;
    ...
};
something.Created += createdEventHandler;

А теперь с помощью вложенных функций:

void OnCreated(object sender, EventArgs e)
{
    something.Created -= OnCreated;
    ...
}
something.Created += OnCreated;

Что выглядит читабельней?


Нашел еще красивый пример, размещенный VladD'ом:

void SortBy<T>(List<T> list, Func<List, double> expr, bool ascending)
{
    int comparerAscending(T t1, T t2)
    {
        return expr(t1).Compare(expr(t2));
    }

    int comparerDescending(T t1, T t2)
    {
        return expr(t2).Compare(expr(t1));
    }

    list.Sort(ascending ? comparerAscending : comparerDescending);
}
MihailPw
  • 6,384
  • А у вас локальные переменные из внешней функции отображаются в дебаггере, когда вы заходите в локальную? У меня почему-то ругается на контекст. – iluxa1810 Jun 20 '17 at 18:14
  • Пример с событиями как-то натянуто выглядит, особенно если убрать инициализацию с помощью null – Grundy Jun 21 '17 at 06:26
  • 1
    @Grundy а вы не сможете избавиться от инициализации с помощью null, когда вам надо будет отписываться от этого события при его срабатывании (переменная еще не создана). – MihailPw Jun 21 '17 at 06:37