23

I am just trying to figure out the technical reason why in the below some lines do not end with a semicolon but other lines do - what is it about a semicolon that C# expects in some lines then others....

In fact whilst writing this I noticed that the statements that have to have curly brackets {} do not need semicolons but the lines that are on its own "Console.WriteLine" do need it.

Really trying to find the technical reasons for this...

ie:

namespace checkPackage     **//no semicolon**
{
    class Program      **//no semicolon**
    {
        static void Main(string[] args)     **//no semicolon**
        {
            listFilesInDirectory(@"C:\Temp\");    **//NEEDS a semicolon**
        }

        static void listFilesInDirectory(string workingDirectory)   **//no semicolon**
        {
            string[] filePaths = Directory.GetFiles(workingDirectory);  **//NEEDS a semicolon**

            foreach (string filePath in filePaths)   **//no semicolon**
            {
                Console.WriteLine(filePath);  **//NEEDS a semicolon**
            }

        }
    }
}
lara400
  • 4,646
  • 13
  • 46
  • 66
  • For 1 where you put end of lines is somewhat arbitrary. Also code blocks { code here } don't need semicolons. – kenny Nov 07 '14 at 14:31
  • 2
    No issues whatever with questioning the status quo. Answer is obvious, language creators made this 'the-way-to-go-forward' with statements. – andrei.ciprian Nov 07 '14 at 15:10
  • 2
    Because the term 'line' almost certainly doesn't appear anywhere in the formal C# language specification. Only toy languages have lines. – user207421 Nov 10 '14 at 09:52
  • ***Note:*** This is *not limited to just C#*. Most languages that uses semi-colons do it this way: PHP, C, C++, Java, etc... – Spencer Wieczorek Nov 10 '14 at 13:02
  • Do not forget, in the two very last lines, you can have an optional semicolon. So the `}` that ends a `class_declaration` and the `}` that ends a `namespace_declaration` may be followed by a semicolon. However, the `}` that ends a method body etc., cannot be followed by a semicolon! The `}` that ends a block does not end in a semicolon, but if you put one it will become an `empty_statement` which is allowed. For example with `if (b) { M(); };` the last semicolon is an `empty_statement`. – Jeppe Stig Nielsen Oct 18 '17 at 23:04

3 Answers3

57

The semi-colon isn't a line terminator... it's a statement terminator. There's a semi-colon at the end of every expression statement and declaration statement.

(if, for etc statements aren't expression or declaration statements.)

So for example:

public class Foo // Part of a class declaration
{
    int x = 0; // Declaration statement

    public void Bar() // Part of a method declaration
    {
        Console.WriteLine(x); // Expression statement (using an invocation expression)
    } // End of the method declaration, but not a declaration statement 

} // End of class declaration, but not a declaration statement

The purpose of requiring them is so that the compiler can tell when you wanted to end the statement instead of continuing on the next line:

 int x = 5;
 int y = x // This isn't the end of the statement!
         + 5; // This is...

One alternative (used by VB, for example) is to have a line continuation where you want to explicitly continue onto the next line even though the current line would be a valid statement.

As noted in comments, the do statement is an anomaly here. I see no obvious reason why this shouldn't be valid:

do { } while (false)

... but it isn't. It may be related to the fact that the plain while statement needs a statement body, e.g. while (true); (empty statement) or while (true) {} (block statement). The closest I can come is "because the C# specification says the do statement needs a semi-colon at the end..."

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • What about a `do {}` loop? – Victor Zakharov Nov 07 '14 at 14:32
  • So, what about a `do {}` loop? I am still curious. :) – Victor Zakharov Nov 07 '14 at 14:45
  • @Neolisk: Oh, you mean because `do { } while (...);` *does* require a semi-colon? – Jon Skeet Nov 07 '14 at 14:47
  • Yes, even more simple, `do {};` vs `if()` (no semicolon at the end), or `do` vs `for` (both are loop operators). – Victor Zakharov Nov 07 '14 at 14:49
  • 3
    @Neolisk: Well there's no such thing as `do` without `while`, for one thing. See my edit though. – Jon Skeet Nov 07 '14 at 14:52
  • Oh okay, I'm coming from VB world, where Do/Loop is perfectly valid. You are right, I just checked in VS, compiler expects a `while`. It's actually harder to write infinite loops in C# it seems. Thanks for the explanation, although I didn't expect anomalies in something like the C syntax. – Victor Zakharov Nov 07 '14 at 14:55
  • 1
    +1 even more "alternative" approach to semicolons is used in JavaScript - semicolon inserted automatically wherever compiler feels useful, also it often feels that it would do that only in cases where semicolon introduces hard to find bugs :) http://stackoverflow.com/questions/12745743/automatic-semicolon-insertion-return-statements – Alexei Levenkov Nov 07 '14 at 15:36
  • this is brilliant answer Jon....FYI - I am going through your C# videos on PluralSight...hence the questioning when I was writing a piece of code! – lara400 Nov 07 '14 at 15:48
  • FYI: `for` can end with a semi-colon. It doesn't need curly brackets. `int pow = 1; for (int i = 0; i < 3; i++, pow *= 5) ;`. The int `pow` now equals 5^3. – user2023861 Nov 07 '14 at 15:51
  • 1
    @user2023861: It *can*, but that's just using an empty statement as the body of the loop. The semicolon belongs to the body of the loop, rather than terminating the for statement as a whole. – Jon Skeet Nov 07 '14 at 16:06
  • It is true that semicolon ends a statement. But now that you mention _"End of class declaration, but not a declaration statement"_, note that C# also allows a `class_declaration` to end with a `;` although few people use that. Same with `namespace_declaration`. So this is allowed: `namespace N { class C { }; };` – Jeppe Stig Nielsen Oct 18 '17 at 23:11
12

The reason? Because the spec says so:

A statement can consist of a single line of code that ends in a semicolon, or a series of single-line statements in a block. A statement block is enclosed in {} brackets and can contain nested blocks.

The foreach definition is followed by a statement, which must either be enclosed in {} or end on a semicolon. This statement is then referred to as the loops body.

This might not be an adequate answer to the question "why". To go deeper into this, you'd really need to ask the designers. I suppose, they wanted to make it close to C-Syntax, as opposed to other languages where the line-break serves a similar purpose. (Python iirc)

If you want a more formal definition, download the C# Language Specification and read section 1.2 to 1.5.

DasKrümelmonster
  • 5,816
  • 1
  • 24
  • 45
6

There are two kinds of statements, simple statements and compound statements. The loops and method declarations are compound statements. Each simple statement end with semicolon but compound statements don't end with semicolon. From msdn

A compound statement consists of zero or more statements enclosed in curly braces ({ }). A compound statement can be used anywhere a statement is expected. Compound statements are commonly called "blocks."

The curly braces specifies the begin and the end of a compound statement.So compiler looks for the braces instead of the semicolon to determine the beginning and the end of the statement.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • Sorry, morning here, I removed my comment. – Victor Zakharov Nov 07 '14 at 14:36
  • Can you explain why a `do {}` loop needs a semicolon? I don't see it any different than an `if` really... – Victor Zakharov Nov 07 '14 at 14:38
  • @Neolisk I think the reason is to distinguish do-while loop from a regular while loop. – Selman Genç Nov 07 '14 at 14:40
  • I don't think this is syntactically enough reason to do this. My guess is that any statement that can have parenthesis after it does not need to end with a `;`, those with no parenthesis must end with a semicolon. I am speculating here, but it's the explanation I don't mind accepting. – Victor Zakharov Nov 07 '14 at 14:50