Вот в этом вопросе поднимается вопрос о планируемых нововведения в c# версии 7. В частности меня заинтересовали так называемые локальные функции. В ответе @VladD есть пример как может быть использована локальная функция: IEnumerable GetOdd(IEnumerable s) { if (s == null) throw new ArgumentNullException() // обратите внимание, `Inner` без параметров IEnumerable Inner() { foreach (var v in s) if (v % 2 != 0) yield return v } return Inner() } но мне кажется данный пример слегка натянутым, в данном случае можно было бы наверно и обойтись без функции Inner(). Так же мне непонятно следующее высказывание: По поводу локальных функций, мне кажется, часто, наоборот, приватные функции классов используются как костыль на отсутствие локальных функций. Часто в приватную функцию выносится хелпер из одной функции, не имеющий значения внутри класса. Локальная функция — более правильный путь для таких функций. У себя в коде я оформляю отдельными методами код на основании следующих правил: Функционал который может быть повторно использован Вынесения функционала в отдельный метод что бы поддерживать стройность функции Прочее
Например: public IEnumerable GetPhonesForNotice(requestId) { var requestState = GetStateOfRequest(int requestId) switch(requestState) { case "Открыта": { return getRecipientsForNewRequest(int requestId) break } case "Закрыта": { return getRecipientsForClosedRequest(int requestId) break } } } private IEnumerable getRecipientsForNewRequest(int requestId) { } private IEnumerable getRecipientsForClosedRequest(int requestId) { } Если я правильно понял то тогда в новой версии языка функции getRecipientsForNewRequest(int requestId), getRecipientsForClosedRequest(int requestId) можно будет реализовать внутри главной функции GetPhonesForNotice(int requestId) но я не понимаю чем это правильней/лучше текущего варианта?
Ответ Мне кажется вот как. Вопрос не в технической стороне дела. (Хотя технические отличия есть, они приведены в конце ответа.) С технической стороны, можно организовать такую же приватную функцию, в которую передавать все параметры явно. А если внутренняя функция должна иметь меньше параметров (например, из-за того, что требуется специфическая сигнатура), можно построить closure. Все технические вопросы решаемы и в рамках старых возможностей. (Точно так же как можно было бы обойтись без свойств и использовать пару функций, без классов, и передавать this в методы явно и т. д.) Дело в том, что мы хотим не загрязнять хелпер-функциями класс, а положить их внутри того, к чему они относятся. Это полная аналогия идеи о том, что класс должен содержать всё то, что необходимо ему для работы, и не требовать «внешнего» управления. Точно так же и тут, функция содержит внутри себя то, что нужно для работы, а приватные вспомогательные методы получаются необходимы лишь там, где они не ограничены смыслом одной функции — то есть, там, где они осмысленны в рамках всего класса. С таким подходом, да, локальные переменные некоторым образом заменяют поля класса, так что в ситуациях, когда раньше вам нужно было создавать внутренний класс и вызывать в нём методы, теперь можно сделать то же самое удобнее с локальными функциями. Кроме того, уменьшение обвязочного кода наподобие неявной передачи переменных всегда важно, так обвязочный код — возможность ошибиться.
В качестве ещё одного мотивирующего примера: void SortBy(List list, Func 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) } Без локальных функций вам пришлось бы создавать внутренние делегаты.
Ещё один сценарий, в котором внутренние функции могут быть полезны — кодогенерация. Если вы генерируете вспомогательную функцию, вы можете случайно попасть на уже занятое имя, вы ведь не знаете, что там в остальной части класса. Если вспомогательная функция «упакована» в другую функцию, этой проблемы не возникает.
Дополнение: Давайте рассмотрим, кроме логических, отличия между локальными функциями и уже существующими средствами языка. Отличие от приватной нелокальной функции состоит, кроме «скрытого» имени, в том, что локальная функция «видит» переменные, объявленные в охватывающей функции до неё. Таким образом, отпадает необходимость передавать параметры в локальную функцию явно, и значит, мы можем более свободно управлять её сигнатурой. (Это может быть важно, см. пример с SortBy.) Отличие локальной функции от аналогичного локально объявленного делегата с лямбда-функцией состоит в том, что делегатная переменная может быть переопределена, имя локальной функции не может быть перепривязано лямбда-функции требуют хитрого синтаксиса для реализации рекурсивного вызова, который таки ломается при последующем изменении делегатной переменной (Y-комбинатор не предлагать!), у локальных функций проблем не возникает лямбда-функция не может быть генератором (yield return) вы не можете объявить обобщённую лямбда функцию (Func f = t => 1 не скомпилируется для неизвестного типа T), с локальными функциями проблем не возникает производительность: делегат означает лишнюю аллокацию экземпляра делегатного типа локальная функция этого недостатка лишена, и дополнительная аллокация нужна лишь для случая нетривиального замыкания. Литература: C# Design Notes for May 20, 2015