Эта тема уже затрагивалась на предыдущих занятиях, но сейчас мы углубим понимание, рассмотрев принципы хранения данных в памяти.
Данное руководство взято с сайта foxdevelop.com. При перепубликации обязательно указывайте источник.
В теле метода можно вкладывать другие блоки кода.
class Program
{
static void Main()
{
int age = 19;
{
int one = 23;
}
}
}
Code language: C# (cs)

Количество блоков кода не ограничено. Их можно располагать последовательно или вкладывать друг в друга на любую глубину вложенности.
class Program
{
static void Main()
{
int age = 19;
{
int one = 23;
{
int two = 45;
{
int three = 56;
}
}
}
}
}Code language: C# (cs)

Важно помнить: инструкция int xxxx = xxx; перед вложенным дочерним блоком является параллельной по отношению к этому блоку.

Например, строка int age = 19; и расположенный под ней вложенный блок кода — это две независимые инструкции. Не принимайте эту конструкцию за тело метода целиком.
Жизненный цикл
Рассмотрим пример
static void Main()
{
int a = 10;
{
int b = 20;
}
}Code language: C# (cs)
В данном примере присутствуют две локальные переменные. Внешняя переменная a относится к внешней области видимости функции Main, а переменная b принадлежит внутреннему вложенному блоку.
Проследим выполнение по шагам и посмотрим, как распределяется память стека.

Шаг 1: Выполняется только int a = 10;. В стеке выделяется память под переменную a со значением 10;
Шаг 2: Переходим во внутренний блок и выполняем int b = 20;. В стек добавляется переменная b. Порядок сверху вниз: b, a;
Шаг 3: Внутренний блок кода завершает работу. Переменная b выгружается из стека, в стеке остаётся только a.
Шаг 4: Метод Main завершает выполнение. Переменная a также удаляется из стека, все переменные программы уничтожаются, работа программы прекращается.
Итог
Переменная, объявленная внутри вложенного блока, начинает свой жизненный цикл с момента объявления и существует до завершения выполнения содержащего её блока.
После завершения работы вложенного блока все локальные переменные из него выгружаются из стека и уничтожаются.
Само тело метода по сути является одним большим блоком кода.
Область видимости
Пока область видимости первой переменной активна, нельзя объявлять другую локальную переменную с одинаковым именем, независимо от глубины вложенности.
Посмотрите пример
static void Main()
{
int a = 10;
{
int a = 20;
}
}Code language: C# (cs)

В примере выше переменная a во внутреннем вложенном блоке имеет то же имя, что и внешняя переменная a. Это вызовет ошибку, компиляция не пройдёт.
Причина: область видимости int a = 10; охватывает все фигурные скобки, внутри которых находится эта строка. В этой области запрещено использовать переменные с повторяющимися именами. Несмотря на то что запись int a = 20; находится во вложенном блоке, этот блок входит в тело метода, где уже объявлена переменная a. Компилятор обнаружит повтор имени и отметит строку волнистой красной линией.
Ограничение сохраняется даже если для второй переменной a выбрать другой тип данных.

В рамках одной области видимости имена переменных должны быть уникальными, тип переменной при этом не имеет значения.

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

Рассмотрим ещё один пример
Возникнет ли конфликт при такой записи кода?
class Program
{
static void Main()
{
int a = 10;
{
double b = 20;
}
{
double b = 30;
}
}
}Code language: C# (cs)
Ответ: нет. Хотя существуют две переменные с именем b, их области видимости не пересекаются, поэтому компиляция завершится успешно. Первая переменная b действует только в своём блоке, вторая — в отдельном блоке. Смотрите иллюстрацию.

Цветом на рисунке отмечены области видимости каждой переменной b. Надеюсь, теперь читателям всё стало понятно.
Вложенные блоки кода и области видимости переменных