TransWikia.com

Qual é a finalidade dos blocos de comandos vazio ou que não pertecem a algum comando?

Stack Overflow em Português Asked by gato on January 11, 2021

Um bloco de comandos é composto de dois ou mais comandos entre chaves {...//Comandos}, eu posso usar eles para as seguintes situações que já conheço:

  • Em um if: if(codicao){...//Comandos}.
  • Em um for: for(inicializacao; condicao; incremento){...//Comandos}.
  • Em um while: while(codicao){...//Comandos}.
  • Em funções: void fazAlgo(){...//Comandos}.
  • E também em classes e outros comandos da linguagem.

No entanto, o C# permite que eu use blocos de comandos para criar escopos sem que seja para as situações acima, ou seja, um bloco de comandos que não pertencem a nenhum dos comandos tradicionais citados acima.

Veja o exemplo criado para ilustrar a situação:

static void Main(string[] args)
{
    int valor1 = 50;

    { //Inicio do bloco
        int valor2 = 100;
        Console.WriteLine("valor1 no bloco: " + valor1);
        Console.WriteLine("valor2 no bloco: " + valor2);
    } //Fim do bloco

    //Bloco vazio.
    { }    

    Console.WriteLine("valor1 fora bloco: " + valor1);
    Console.ReadKey();
}

No exemplo acima que utilizei para ilustração a um bloco que contem uma variável de tipo inteiro valor2, eu gostaria de saber qual é a finalidade de um bloco de comandos como este? E ainda o compilador me permitiu criar um bloco vazio { }, o compilador não acusou nenhum erro correspondente a este bloco vazio, tem alguma utilidade em usar um bloco vazio? Já que ele é permitido pelo compilador.

2 Answers

Como já deu para perceber, a definição do que é um bloco de comando já está errada. Ele permite zero ou mais comandos (não gosto muito da tradução de statement para comando, mas ela a mais próxima que temos, então aceitável se a pessoa entender bem o que isto significa).

Método vazio

Se for um método que deve fazer nada dentro, aí tem:

public void Exemplo() {}

Este é um método que explicitamente deve fazer nada. É raro ter uma necessidade assim, mas tem sua utilidade. É mais comum em métodos virtuais. Ou o virtual deve fazer nada, mas deixa seus descendentes fazerem ou o que sobrescreve deve eliminar o comportamento do ascendente. Se a opção for esta então deve ser muito bem pensada.

Note que um método vazio é diferente de um método virtual ou parcial sem implementação. O vazio tem uma implementação, que é fazer nada. E se é um erro chamar aquele método que foi obrigado a implementar por algum contrato, deve em primeira opção pensar se deveria usar aquele contrato, e em segunda optar por lançar uma exceção (NotImplementedException) para não usá-lo em vez de engolir a execução. Os puristas dirão que não deve usar a segunda opção, os pragmáticos dirão que não é tão grave fazer isto, ainda mais se tiver alguma ferramenta que ajude detectar isto antes de ir para o runtime.

Bloco vazio

De fato usar o bloco vazio desta forma não tem utilidade. Mas por que deveria dar um erro?

Lembrando que o compilador não tenta ser mais esperto do que ele precisa. Daria muito trabalho para ficar verificando algo que não faz diferença. O compilador tem coisas mais importantes para fazer. Além disto o máximo que poderia dar é um warning, afinal não causa erro algum fazer isto. Mesmo assim seria um exagero, porque mesmo warnings devem ser para casos onde tem potencial real para causar problemas. O que leva a dizer que muitos programadores não tratam warnings como erros, embora eles sejam, e vão causar problemas. Eu já peguei um código legado de 120 mil linhas que possuía 600 mil warnings. E o código "funcionava" :D No máximo isto deveria ser objeto de análise estática onde os falsos positivos são esperados.

Novo escopo

O caso do bloco sem estar vinculado ao comando é útil em casos onde precisa introduzir uma variável e mesmo nome, assim fica legível onde já existe outra variável com mesmo nome.

Em geral o código pode ser modificado para evitar isto, mas também não é tão necessário. Muitas vezes quando isto é necessário significa que o método está complicado demais.

Estas duas variáveis possuem o mesmo nome mas são completamente independentes.

{
    {
        int x = 0;
    }

    {
        int x = 0;
    }
}

Isto é válido. Já o abaixo não compila porque a variável de um escopo pode estar escondendo a outra:

{
    {
        int x = 0;
    }
    int x = 0;
}

Faria mais sentido em casos assim:

{
    if (true) { //aqui iria uma condição real
        int x = 0;
    }

    {
        int x = 0;
    }
}

Coloquei no GitHub para referência futura.

Sem o bloco aparentemente desnecessário isto não compilaria. O primeiro x poderia estar "sombreando" o segundo. Com o bloco eles se tornam independentes e compila.

Pra falar a verdade, a utilidade disto é algo bastante teórica. Na prática é possível produzir código legível sem ter que se preocupar com isto. Neste caso específico se não existisse este bloco não faria grande falta. Claro que alguns acham que é importante. Vejo tanta coisa que é mais importante e não existe na linguagem.

Correct answer by Maniero on January 11, 2021

Não, não há nenhuma utilidade em usar o bloco {} vazio, ele simplesmente é ignorado pelo compilador, a utilidade dele se dá apenas quando está sendo usado junto a outro comando sendo eles: if, else,while, etc. Mas sozinho é apenas ignorado da mesma forma que o begin/end é utilizado junto ao if, else , while no Delphi. Se você criar um begin/end vazio o compilador Delphi também irá compilar normalmente como em C#, pois apenas ignorou o bloco vazio. Espero ter ajudado.

Answered by Viniam on January 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP