На английском языке их называют Local Functions. Данная возможность появилась в C# 7.0.
Ранее мы разобрали вызов методов. Внутри блока кода одного метода можно вызывать другие методы по следующим правилам:
- Методы внутри одного класса: вызываются напрямую по имени с передачей аргументов;
- Методы другого класса: сначала нужно создать экземпляр соответствующего класса, а целевой метод обязательно должен иметь модификатор
public.
Начиная с C# 7.0 внутри одного метода можно объявлять самостоятельные функции, их называютлокальными функциями:
- Изоляция: их можно вызывать только из внешнего метода, в котором они объявлены; внешний код не имеет к ним доступа;
- Преимущества: логика кода группируется вместе, повышается читаемость и упрощается поддержка;
- Правила объявления: в отличие от локальных переменных локальные функции можно определять в любом месте внешнего метода, предварительное объявление не требуется.
Локальные функции могут захватывать локальные переменные внешнего метода, но их область видимости ограничена содержащим методом.
Сначала разберем один важный момент:
Локальные переменные внутри функции выполняются сверху вниз. Переменную нужно объявить до использования, обратный порядок не допускается.
Рассмотрим код ниже: переменная hour создается ниже, поэтому обращаться к ней до объявления нельзя.
int GetHours()
{
Console.WriteLine(hour);
int hour = DateTime.Now.Hour;
return hour;
}Code language: C# (cs)
Несмотря на то что область видимости hour охватывает весь метод, использовать переменную до объявления запрещено.

Появится ошибка с красной волнистой линией, текст ошибки показан на изображении выше.
С обычными методами ситуация другая. Метод, объявленный ниже, может вызывать метод выше. Методы класса являются членами класса и хранятся в таблице методов Method Table. При вызове система обращается к этой таблице, выполнение не идет строго сверху вниз.

В примере ниже метод Main вверху вызывает метод GetHours, объявленный позже. Это поведение отличается от правил работы локальных переменных.
class Program
{
static void Main()
{
Program program = new Program();
program.GetHours();
}
int GetHours()
{
int hour = DateTime.Now.Hour;
return hour;
}
}Code language: C# (cs)
Вернемся к локальным функциям.
Посмотрим пример:
class Program
{
static void Main()
{
Program program = new Program();
program.ZoomIn();
}
public void ZoomIn()
{
// Локальную функцию можно вызывать до ее объявления
int results0 = ZoomIn5(10);
Console.WriteLine($"A: {results0}");
// Локальная функция: умножает переданное значение val на 5 и возвращает результат
int ZoomIn5(int val)
{
return val * 5;
}
// Вызов локальной функции
int results = ZoomIn5(10);
Console.WriteLine($"B: {results}");
int results2 = ZoomIn5(5);
Console.WriteLine($"C: {results2}");
}
}
Code language: C# (cs)
Область видимости локальной функции ограничена методом, в котором она объявлена. Ее можно вызывать как до, так и после места определения внутри этого метода.
Кроме того, имя локальной функции может совпадать с именем внешнего метода.
class Program
{
static void Main()
{
Program program = new Program();
program.ZoomIn5();
}
public void ZoomIn5()
{
// Локальную функцию можно вызывать до ее объявления
int results0 = ZoomIn5(10);
Console.WriteLine($"A: {results0}");
// Локальная функция: умножает переданное значение val на 5 и возвращает результат
int ZoomIn5(int val)
{
return val * 5;
}
// Вызов локальной функции
int results = ZoomIn5(10);
Console.WriteLine($"B: {results}");
int results2 = ZoomIn5(5);
Console.WriteLine($"C: {results2}");
}
}
Code language: C# (cs)
В примере выше и внешний метод, и локальная функция называются ZoomIn5. Конфликта имен не возникает из-за разных областей видимости, однако такой стиль написания кода не рекомендуется.
Локальные функции