Empty semicolon doesn’t make a mistake?

Asked

Viewed 502 times

21

I was working on a project and unintentionally bumped into the semicolon that ended up being inserted well after a if. I was intrigued because Visual Studio did not point out as an error, and when trying to compile the project I was successful.

The code went like this:

if(alguma_coisa)
{
   //Bloco lógico
};

Motivated by curiosity, I could notice that it is also possible to insert a semicolon at the end of loops like while, for and foreach.

I showed it to a friend and he revealed the possibility of inserting the semicolon several times in sequence in the same line as follows:

if(alguma_coisa)
{
   //Bloco lógico
}; ; ; ; ; ;

And yet the project is compiled without any problem.

A build error should not be generated?
Why is that allowed?

6 answers

28


The semicolon serves to determine the end of an instruction. What happens in this case is that "the instruction" does nothing.

Do this:

if(true)
{
};

is the same thing as doing

if(true)
{    
}
; //Final da "instrução" que está vazia

18

This is a perfectly valid, yet innocuous syntax. Each semicolon represents the end of a statement; without any content, the block is simply ignored when compiling.

  • 4

    I can barely see your movements

  • 8

    for those who are not mine - http://www.dicionarioinformal.com.br/in%C3%B3cua/

14

Between the closing of the if which is the } and the ; inserted is a block of code that does nothing. Same thing between a ; and another ;

11

I think the question has been well answered, but there is one case I think it is important to mention here.

Just as one can have semicolons without causing build errors, the following code also does not cause build errors

{
    //bloco lógico
}

See that it’s a block between { } without any logical construction, is not a if, for, while or any method.

The compiler allows me to do this and it separates the context from variables if they are declared, for example

{
    var i = 1;
    Console.Write(i); //ok
}
Console.Write(i); //erro de compilação, i não existe no contexto atual

But then what does this have to do with the ;? In your first example you placed a semicolon after closing the block of if, but imagine that you had done it by accident

if(alguma_coisa);
{
   //Bloco lógico
}

No build error would occur, what would happen during the run is that this Bloco lógico would always be executed, regardless of the if, and I think this is one of the most common problems that can happen with a semicolon added by mistake.

Another interesting case is that of a for

int i;
for(i = 0; i < 10; i++);
{
    Console.Write(i);
}

Then you would see on the console only one value, the 10, that should never appear.

But this error is less common since the direct variable is usually declared in the for, and in this case a build error would occur

for(int i = 0; i < 10; i++);
{
    Console.Write(i); //erro de compilação, i não existe no contexto atual
}

11

At the time of the question I understood the answers as certain and I voted for them. But they are talking about the consequence and not the cause.

It is true that it seems that intelligently the compiler eliminates the ; which has no practical use, it is true that this character is usually used as a terminator for statement. Everything that is answered is right and works, but has failed to speak because it works.

But in this case what you get is a Empty statement. This in the language specification. And there is Warning when it may have been used unintentionally.

The example of LINQ’s answer shows that what looks terminator is actually just one Empty statement on the same line. Then

if(true)
{
};

is really the same as

if(true)
{    
}
;

So it is not a terminator for the block of if, he’s another statement completely different and doing nothing.

  • This has some performance loss however small?

  • 1

    @Marconciliosouza In PHP there is always because it is an interpreted language, because it has an extra character to interpret, but it is a very small loss and only hurts once, even if it is in a loop, after all it is only in the process of interpretation and not execution. Note that this "loss" is the same as giving a ENTER, a space, nothing you should really worry about.

  • In my opinion the answer is good, but I think I could be better talking directly about the lexical analyzer. Not just implicitly in "another completely different statement".

  • @Guilhermelautert did not understand what you mean by that.

  • Regardless of the language being interpreted or compiled, who defines the statement is the lexical analyzer, the analyzer who defines where starts/ends. In this way I believe I would be more complete explaining this fact.

9

The compiler of C# - Roslyn, in the most current version - has "intelligence" to supply these situations.

  • Multiple semicolons: return; ; ; => return;
  • String concatenation: string a = "b" + "c"; => var a = string.Concat("b", "c");
  • Surplus comma: var a = new int[] {1,2,3,}; => var a = new[]{1,2,3};

Including deletion of declared and unused variables:

var a = UmMetodoQualquer(); => UmMetodoQualquer();

That’s why there are compilation errors in these cases, because the C# compiler analyzes and makes these small "fixes".

Browser other questions tagged

You are not signed in. Login or sign up in order to post.