Existem alguns casos (bastante raros) em que existe o risco de:
reutilizar uma variável que não se destina a ser reutilizada (veja o exemplo 1),
ou usando uma variável em vez de outra, feche semanticamente (veja o exemplo 2).
Exemplo 1:
var data = this.InitializeData();
if (this.IsConsistent(data, this.state))
{
this.ETL.Process(data); // Alters original data in a way it couldn't be used any longer.
}
// ...
foreach (var flow in data.Flows)
{
// This shouldn't happen: given that ETL possibly altered the contents of `data`, it is
// not longer reliable to use `data.Flows`.
}
Exemplo 2:
var userSettingsFile = SettingsFiles.LoadForUser();
var appSettingsFile = SettingsFiles.LoadForApp();
if (someCondition)
{
userSettingsFile.Destroy();
}
userSettingsFile.ParseAndApply(); // There is a mistake here: `userSettingsFile` was maybe
// destroyed. It's `appSettingsFile` which should have
// been used instead.
Esse risco pode ser mitigado com a introdução de um escopo:
Exemplo 1:
// There is no `foreach`, `if` or anything like this before `{`.
{
var data = this.InitializeData();
if (this.IsConsistent(data, this.state))
{
this.ETL.Process(data);
}
}
// ...
// A few lines later, we can't use `data.Flows`, because it doesn't exist in this scope.
Exemplo 2:
{
var userSettingsFile = SettingsFiles.LoadForUser();
if (someCondition)
{
userSettingsFile.Destroy();
}
}
{
var appSettingsFile = SettingsFiles.LoadForApp();
// `userSettingsFile` is out of scope. There is no risk to use it instead of
// `appSettingsFile`.
}
Parece errado? Você evitaria essa sintaxe? É difícil entender pelos iniciantes?
c#
coding-style
language-features
scope
Arseni Mourzenko
fonte
fonte
Respostas:
Se sua função é tão longa que você não consegue mais reconhecer efeitos colaterais indesejados ou reutilizar ilegalmente variáveis, é hora de dividi-la em funções menores - o que torna um escopo interno inútil.
Para apoiar isso com alguma experiência pessoal: há alguns anos, herdei um projeto legado em C ++ com ~ 150K linhas de código, e ele continha alguns métodos usando exatamente essa técnica. E adivinhem - todos esses métodos foram muito longos. À medida que refatoramos a maior parte desse código, os métodos se tornaram cada vez menores, e tenho certeza de que não existem mais métodos de "escopo interno" restantes; eles simplesmente não são necessários.
fonte
É muito mais fácil para um iniciante (e qualquer programador) pensar em:
do que pensar em:
Além disso, do ponto de vista do leitor, esses blocos não têm papel aparente: removê-los não afeta a execução. O leitor pode coçar a cabeça tentando adivinhar o que o codificador queria alcançar.
fonte
Usar um escopo é tecnicamente correto. Mas se você quiser tornar seu código mais legível, extraia essa parte em outro método e dê um nome completo a esse significado. Dessa forma, você pode fornecer um escopo de suas variáveis e também um nome de sua tarefa.
fonte
Concordo que a reutilização de variável é mais frequentemente do que um cheiro de código. Provavelmente, esse código deve ser refatorado em blocos menores e independentes.
Há um cenário específico, OTOH, em C #, quando eles tendem a aparecer - ou seja, ao usar construções de casos de comutação. A situação é muito bem explicada em: declaração C # Switch com / sem colchetes ... qual é a diferença?
fonte