Esse conteúdo já foi abordado nas aulas anteriores, mas vamos aprofundar o entendimento analisando como funciona o armazenamento na memória.
Este tutorial é originário do foxdevelop.com. Por favor, informe a fonte ao republicar.
É possível aninhar outros blocos de código dentro do corpo de um método.
class Program
{
static void Main()
{
int age = 19;
{
int one = 23;
}
}
}
Code language: C# (cs)

Não há limite para a quantidade de blocos. Eles podem ser organizados sequencialmente ou aninhados em vários níveis, sem restrição de profundidade.
class Program
{
static void Main()
{
int age = 19;
{
int one = 23;
{
int two = 45;
{
int three = 56;
}
}
}
}
}Code language: C# (cs)

Atenção: linhas como int xxxx = xxx; acima de um bloco filho aninhado são instruções paralelas a esse bloco.

Por exemplo, int age = 19; e o bloco de código aninhado abaixo são duas instruções paralelas. Não confunda essa estrutura com o corpo completo de um método.
Ciclo de Vida
Veja um exemplo
static void Main()
{
int a = 10;
{
int b = 20;
}
}Code language: C# (cs)
Neste exemplo temos duas variáveis locais. A variável externa a pertence ao escopo principal da função Main, enquanto b está dentro do bloco aninhado interno.
Vamos acompanhar a execução passo a passo para ver como a memória de pilha é gerenciada.

Passo 1: Apenas int a = 10; é executado. A pilha aloca espaço para a com valor igual a 10;
Passo 2: Entramos no bloco interno e executamos int b = 20;. A pilha recebe a variável b. De cima para baixo na pilha: b, a;
Passo 3: O bloco interno termina a execução. b é removido da pilha e apenas a permanece.
Passo 4: O método Main finaliza. a também sai da pilha, todas as variáveis do programa são destruídas e o programa encerra.
Resumo
Variáveis declaradas dentro de blocos aninhados iniciam seu ciclo de vida na linha de declaração e terminam ao final do bloco onde foram criadas.
Quando um bloco aninhado conclui sua execução, todas as variáveis locais desse bloco são removidas e destruídas da pilha.
O corpo de um método nada mais é do que um grande bloco de código.
Escopo
Enquanto o escopo de uma variável existir, não é possível declarar outra variável local com o mesmo nome, independentemente de quantos níveis de aninhamento houver.
Confira o exemplo
static void Main()
{
int a = 10;
{
int a = 20;
}
}Code language: C# (cs)

Nesse trecho, a variável a do bloco interno tem o mesmo nome da variável a externa. Isso causa um erro e a compilação não passa.
Explicação: O escopo de int a = 10; compreende todas as chaves que envolvem essa linha. Nesse escopo não são permitidos nomes repetidos. Mesmo que int a = 20; esteja dentro de um bloco aninhado, esse bloco está contido no corpo do método onde a já existe. O compilador detecta o conflito e marca a linha com um risco vermelho ondulado.
A regra continua valendo mesmo se você alterar o tipo de dado da segunda variável a.

Dentro de um mesmo escopo, os nomes das variáveis devem ser únicos, independente do seu tipo de dado.

Conforme a figura, o escopo da variável externa a está em amarelo e o da interna em verde. Fica evidente que o escopo externo engloba completamente o interno, gerando o conflito.
A solução é trocar o nome da variável a interna.

Veja mais um exemplo
Teremos conflito ao escrever o código dessa forma?
class Program
{
static void Main()
{
int a = 10;
{
double b = 20;
}
{
double b = 30;
}
}
}Code language: C# (cs)
A resposta é não. Embora existam duas variáveis chamadas b, seus escopos não se sobrepõem, então a compilação ocorre sem erros. O primeiro b vale apenas no seu bloco e o segundo pertence a um bloco separado. Confira a imagem abaixo.

As áreas coloridas representam o escopo de cada variável b. Espero que agora todos os leitores consigam entender.
Blocos de código aninhados e escopo de variáveis