Por que C # permitem que blocos de código sem instrução anterior (por exemplo if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Por que C # permitem que blocos de código sem instrução anterior (por exemplo if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Respostas:
No contexto que você dá, não há significado. Escrever uma string constante no console funcionará da mesma maneira em qualquer lugar no fluxo do programa. 1
Em vez disso, você normalmente os usa para restringir o escopo de algumas variáveis locais. Isso é mais elaborado aqui e aqui . Olhe para a resposta de João Angelo e a resposta de Chris Wallis para pequenos exemplos. Eu acredito que o mesmo se aplica a algumas outras linguagens com sintaxe de estilo C também, embora não sejam relevantes para esta questão.
1 A menos, é claro, que você decida tentar ser engraçado e criar sua própria Console
aula, com um Write()
método que faz algo totalmente inesperado.
out
parâmetro para uma implementação de interface escrita em outro idioma, e essa implementação lê a variável antes de gravá-la.
O { ... }
tem pelo menos o efeito colateral de introduzir um novo escopo para variáveis locais.
Eu tendo a usá-los em switch
declarações para fornecer um escopo diferente para cada caso e, dessa forma, permitir-me definir uma variável local com o mesmo nome no local mais próximo possível de seu uso e também denotar que eles são válidos apenas no nível do caso.
{}
como manter os emblemas de ouro chegando ... :)
Não é tanto um recurso do C # quanto um efeito colateral lógico de muitas linguagens de sintaxe C que usam colchetes para definir o escopo .
Em seu exemplo, as chaves não têm efeito algum, mas no código a seguir elas definem o escopo e, portanto, a visibilidade de uma variável:
Isso é permitido porque i sai do escopo no primeiro bloco e é definido novamente no próximo:
{
{
int i = 0;
}
{
int i = 0;
}
}
Isso não é permitido porque i saiu do escopo e não é mais visível no escopo externo:
{
{
int i = 0;
}
i = 1;
}
E assim por diante.
{}
conhecidos como parênteses?
One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context;
Em qualquer caso, eles não são parênteses, mas 'colchetes' parece OK.
Considero {}
como uma declaração que pode conter várias declarações.
Considere uma instrução if que exista de uma expressão booleana seguida por uma instrução. Isso funcionaria:
if (true) Console.Write("FooBar");
Isso também funcionaria:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
Se não estou enganado, isso é chamado de instrução em bloco.
Uma vez que {}
pode conter outras instruções, também pode conter outras {}
. O escopo de uma variável é definido por seu pai {}
(instrução de bloco).
O que estou tentando mostrar é que {}
é apenas uma declaração, então não requer um se ou qualquer coisa ...
A regra geral em linguagens de sintaxe C é "qualquer coisa no meio { }
deve ser tratada como uma única instrução, e pode ir a qualquer lugar que uma única instrução":
if
.for
, while
ou do
.Para todos os efeitos, é como a gramática da linguagem incluiu isto:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
Ou seja, "uma declaração pode ser composta de (várias coisas) ou de uma chave de abertura, seguida por uma lista de declarações (que pode incluir uma ou mais declarações), seguida de uma chave fechada". IE "um { }
bloco pode substituir qualquer instrução, em qualquer lugar". Incluindo no meio do código.
Não permitir um { }
bloco em qualquer lugar que uma única instrução possa ir tornaria a definição da linguagem mais complexa .
Porque C ++ (e java) permitia blocos de código sem uma instrução anterior.
C ++ permitiu isso porque C permitiu.
Você poderia dizer que tudo se resume ao fato de que o design de linguagem de programa dos EUA (baseado em C) venceu, em vez do design de linguagem de programa europeu ( baseado em Modula-2 ).
(As instruções de controle atuam em uma única instrução, as instruções podem ser grupos para criar novas instruções)
// if (a == b)
// if (a != b)
{
// do something
}
Você perguntou "por que" C # permite blocos de código sem instruções anteriores. A pergunta "por que" também poderia ser interpretada como "quais seriam os possíveis benefícios desse construto?"
Pessoalmente, eu uso blocos de código sem instrução em C #, onde a legibilidade é muito melhorada para outros desenvolvedores, embora tenha em mente que o bloco de código limita o escopo das variáveis locais. Por exemplo, considere o seguinte snippet de código, que é muito mais fácil de ler graças aos blocos de código adicionais:
OrgUnit world = new OrgUnit() { Name = "World" };
{
OrgUnit europe = new OrgUnit() { Name = "Europe" };
world.SubUnits.Add(europe);
{
OrgUnit germany = new OrgUnit() { Name = "Germany" };
europe.SubUnits.Add(germany);
//...etc.
}
}
//...commit structure to DB here
Estou ciente de que isso poderia ser resolvido de forma mais elegante, usando métodos para cada nível de estrutura. Mas, novamente, tenha em mente que coisas como semeadores de dados de amostra geralmente precisam ser rápidos.
Portanto, mesmo que o código acima seja executado linearmente, a estrutura do código representa a estrutura do "mundo real" dos objetos, tornando mais fácil para outros desenvolvedores entender, manter e estender.