Semicolons in C#

Viewed 25185

Why are semicolons necessary at the end of each line in C#? Why can't the complier just know where each line is ended?

12 Answers

The line terminator character will make you be able to break a statement across multiple lines.

On the other hand, languages like VB have a line continuation character (and may raise compile error for semicolon). I personally think it's much cleaner to terminate statements with a semicolon rather than continue using undersscore.

Finally, languages like JavaScript (JS) and Swift have optional semicolon(s), but at least JS has a convention to always put semicolons (even if not required, which prevents accidents).

No, the compiler doesn't know that a line break is for statement termination, nor should it. It allows you to carry a statement to multilines if you like.

See:

string sql = @"SELECT foo
               FROM bar
               WHERE baz=42";

Or how about large method overloads:

CallMyMethod(thisIsSomethingForArgument1,
             thisIsSomethingForArgument2,
             thisIsSomethingForArgument2,
             thisIsSomethingForArgument3,
             thisIsSomethingForArgument4,
             thisIsSomethingForArgument5,
             thisIsSomethingForArgument6);

And the reverse, the semi-colon also allows multi-statement lines:

string s = ""; int i = 0;

How many statements is this?

for (int i = 0; i < 100; i++) // <--- should there be a semi-colon here?
Console.WriteLine("foo")

Semicolons are needed to eliminate ambiguity.

So that whitespace isn't significant except inside identifiers and keywords and such.

Strictly speaking, this is true: if a human could figure out where a statement ends, so can the compiler. This hasn't really caught on yet, and few languages implement anything of that kind. The next version of VB will probably be the first language to implement a proper handling of statements that require neither explicit termination nor line continuation [source]. This would allow code like this:

Dim a = OneVeryLongExpression +
        AnotherLongExpression
Dim b = 2 * a

Let's keep our fingers crossed.

On the other hand, this does make parsing much harder and can potentially result in poor error messages (see Haskell).

That said, the reason for C# to use a C-like syntax was probably due to marketing reasons more than anything else: people are already familiar with languages like C, C++ and Java. No need to introduce yet another syntax. This makes sense for a variety of reasons but it obviously inherits a lot of weaknesses from these languages.

I personally agree with having a distinct character as a line terminator. It makes it much easier for the compiler to figure out what you are trying to do.

And contrary to popular belief it is not possible 100% of the time to for the compiler to figure out where one statement end and another begins without assistance! There are edge cases where it is ambiguous whether it is a single statement or multiple statements spanning several lines.

Read this article from Paul Vick, the technical lead of Visual Basic to see why its not as easy as it sounds.

It can be done. What you refer to is called "semicolon insertion". JavaScript does it with much success, the reason why it is not applied in C# is up to its designers. Maybe they did not know about it, or feared it might cause confusion among programmers.

For more details in semicolon insertion in JavaScript, please refer to the ECMA-script standard 262 where JavaScript is specified.

I quote from page 22 (in the PDF, page 34):

  • When, as the program is parsed from left to right, the end of the input stream of tokens is encountered and the parser is unable to parse the input token stream as a single complete ECMA Script Program, then a semicolon isa utomatically inserted at the end of the input stream.

  • When, as the program is parsed from left to right, a token is encountered that is allowed by some production of the grammar, but the production is a restricted production and the token would be the first token for a terminal or nonterminal immediately following the annotation “[no LineTerminator here]” with in the restricted production (and there fore such a token is called a restricted token), and the restricted token is separated fromt he previous token by at least one LineTerminator, then a semicolon is automatically inserted before the restricted token.

However, there is an additional overriding condition on the preceding rules: a semicolon is never inserted automatically if the semicolon would then be parsed as an empty statement or if that semicolon would become one of the two semicolons in the header of a for statement (section 12.6.3).

[...]

The specification document even contains examples!

Another good reason for semicolons is to isolate syntax errors. When syntax errors occur the semicolons allow the compiler to get back on track so that something like

a = b + c = d

can be disambiguated between

a = b + c; = d

with the error in the second statement or

a = b + ; c = d

with the error in the first statement. Without the semicolons, it can be impossible to say where a statement ends in the presence of a syntax error. A missing parenthesis might mean that the entire latter half of your program may be considered one giant syntax error rather than being syntax checked line by line.

It also helps the other way - if you meant to write

a = b; c = d;

but typoed and left out the "c" then without semis it would look like

a = b = d

which is valid and you'd have a running program with a bad and difficult to locate bug so semicolons can often help catch errors that otherwise would look like valid syntax. Also, I agree with everybody on readability. I don't like working in languages without some sort of statement terminator for that reason.

I've been mulling this question a bit and if I may take a guess at the motivations of the language designers:

C# obviously has semicolons because of its heritage from C. I've been rereading the K&R book lately and it's pretty obvious that Dennis Ritchie really didn't want to force programmers to code the way he thought was best. The book is rife with comments like, "Although we are not dogmatic about the matter, it does seem that goto statements should be used rarely, if at all" and in the section on functions they mention that they chose one of many format styles, it doesn't matter which one you pick, just be consistent.

So the use of an explicit statement terminator allows the programmer to format their code however they like. For better or worse, it seems consistent with how C was originally designed: do it your way.

I would say that the biggest reason that semicolons are necessary after each statement is familiarity for programmers already familiar with C, C++, and/or Java. C# inherits many syntactical choices from those languages and is not simply named similarly to them. Semicolon-terminated statements is just one of the many syntax choices borrowed from those languages.

You could accurately argue that requiring a semicolon to terminate a statement is superfluous. It is technically possible to remove the semicolon from the C# language and still have it work. The problem is that it leaves room for misinterpretation by humans. I would argue that the necessity of semicolons is the disambiguation for the sake of humans, not the compiler. Without some form of statement delimitation, it is much harder for humans to interpret consise staements such as this:

int i = someFlag ? 12 : 5 int j = i + 3

The compiler should be able to handle this just fine, but to a human the below looks much better

int i = someFlag ? 12 : 5; int j = i + 3;
Related