2

I am confused by the terminology of Compiler error CS0201. It says that

Only assignment, call, increment, decrement, and new object expressions can be used as a statement

So according to this anything except above cannot be a statement. Then how does below line does not produce the above error.

Anyclass obj;

Here we don't have any assignment or call or increment or decrement or new object expression.

I know I am missing something as the official documentation contradicts this error by saying declaration is also a statement.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Swanand Pangam
  • 858
  • 1
  • 10
  • 25
  • So you want to say that it should say *expression statement* instead of *statement* since the error message doesn't give an exhaustive list? – Patrick Hofman May 24 '18 at 17:23
  • @PatrickHofman what I am saying is, the documentation and error message are contradicting themselves or I am missing something important. – Swanand Pangam May 24 '18 at 17:24
  • How much do you know about parse trees? – Patrick Hofman May 24 '18 at 17:25
  • 1
    @TJWolschon OP says that according to his reading of the docs, it shouldn't compile. – Patrick Hofman May 24 '18 at 17:28
  • @PatrickHofman So this question is only about microsoft's documentation then? Doesn't seem like it's very on topic for SO, imo. – Daxtron2 May 24 '18 at 17:32
  • 3
    This is a declaration, would it not fall under the category of "new object"? – Jonathon Chase May 24 '18 at 17:33
  • @TJWolschon I believe this site clearly says **online community for programmers to learn, share their knowledge** and not just for solving errors. Regarding your second point, the code and documentation are in sync but the compiler states otherwise which I want to learn. Thanks – Swanand Pangam May 24 '18 at 17:35
  • 1
    I don't feel like we're gaining any knowledge over something like this though. Everyone knows that documentation isn't always 100% accurate, like in this situation. I don't think the discussion itself is bad, in fact, it's a good one to have, but it needs to be the right setting and audience. Very few people here would be able to affect the documentation, (outside of some microsoft employees who hang out on SO). You could also submit a PR to fix this yourself if you wanted to. – Daxtron2 May 24 '18 at 17:38
  • 1
    @JonathonChase No. If you read the documentation it shouldn't. – Patrick Hofman May 24 '18 at 17:39
  • 2
    @TJWolschon It is not about the documentation, is it about the compiler error. – Patrick Hofman May 24 '18 at 17:39
  • 2
    @TJWolschon the docs is hosted on Github. You can do a pull request yourself. – Patrick Hofman May 24 '18 at 17:40
  • 1
    Even then, I just don't see how this post really helps anyone here. Like I said, I'm not against the discussion at all, I just don't know if anyone will get much use out of it here. We know that it works, the compiler's errors are out of our control. – Daxtron2 May 24 '18 at 17:48
  • 1
    The documentation is inconsistent and incomplete. The table of types of statements seems complete though, but the paragraphs at the top don't contain an exhaustive list of those types. Perhaps it isn't meant to. – Lasse V. Karlsen May 24 '18 at 17:51

1 Answers1

17

The error text is:

Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Your question includes the assertion:

So according to this anything except above cannot be a statement.

No, that is an incorrect conclusion.

First of all, what you're doing is simply a bad idea. Do not read the error messages to learn what the rules of the language are. The error messages are there to tell you what's wrong with programs that are not legal. They are not intended to be a guide as to what is legal! Error messages are written assuming that the context is that you're looking at an illegal program at the same time as you are reading the error. Error messages are a single sentence; the language specification is 800 pages long and has a lot more detail. Read the specification.

Second: a correct conclusion is: according to that error message, no other expression can be used as a statement. This error message is only produced in contexts where there is an invalid expression being used in a context where a statement is expected.

Then how does below line does not produce the above error.

Anyclass obj;

That line is not an expression, so the error message doesn't apply to it.

You made a wrong conclusion from this error message, which is evidence that this error message is confusing, and for that reason alone we could argue that it could be changed. For example, we could say "expression statement" instead of "statement". Or we could diagnose the larger problem, and report "This statement consists of an expression that is typically only useful for its value, which is discarded. Only increment...", and now the purpose of the message becomes more clear.

There are a great many error messages in C# that are confusing. For example, consider my personal favorite:

A params parameter must be the last parameter in a formal parameter list

If you didn't know how params parameters worked, it would be reasonable to conclude from this error message that (params int[] x, params int[] y) is legal -- after all, a params parameter is the last parameter in a formal parameter list! It would also be sensible to conclude that (int x) is wrong, because a params parameter is not the last parameter in that list!

Of course we know that what the error message means is "if you have a params parameter then that parameter must be the last one in the formal parameter list".

Error messages are one of the most important outputs of any compiler, and yet they are often confusing, ungrammatical, abstruse and unhelpful. Why is that?

  • Compiler writers are not English majors.
  • Compiler error messages are often written with the compiler writer's convenience in mind, not with the user's convenience. Example: I spent literally weeks improving overload resolution error message reporting logic for problems involving lambdas so that adding LINQ to C# 3 did not make the error messages misleading. That was a lot of work, and it took away effort that could have been spent on other work.
  • Compiler writers are domain experts who can find it difficult to get back into "beginner mind".

But hardest of all:

  • to write an error message, a compiler writer must imagine themselves to be in the mental state of someone who has made a mistake, and figure out what will remove the erroneous mental state in a manner that leads to a correct program being written. That's a hard problem in human psychology! Compiler writers are not mind readers, but they are asked to be all the time.

So what's happening here is: the compiler is expecting a statement. It found expression ; which looks like an expression statement. But only a subset of expressions are legal in an expression statement; if it is not one of those, then this error is reported.


If you have an idea for how an error message can be improved, please don't report it here; start a discussion on the Roslyn github forum.


Speaking of which: the error message you quote is wrong. It was never updated when await was added to the language. await x is an expression and await x; is legal.

Community
  • 1
  • 1
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • So, between statement and expression which one is super-type of the other or are they even related to each other. "That line is not an expression, so the statement doesn't apply to it" Then what is this line like if not a statement or expression? Thanks – Swanand Pangam May 24 '18 at 18:15
  • 1
    @SwanandPangam: There is no "is a kind of" relationship between *statement* and *expression*. An *expression statement* is a kind of *statement*. The C# compiler detects code fragments of the form `expression;` and gives this error if the expression is not legal in an expression statement. – Eric Lippert May 24 '18 at 18:19
  • 1
    @SwanandPangam: The statement `X x;` is a declaration statement. It's a kind of statement. But `X x` is not an expression, so the error message about valid expressions in a statement does not apply to it. – Eric Lippert May 24 '18 at 18:21
  • "So any line should be either a statement or if its an expression then it should be either assignment, call, increment, decrement, or new object" this is the closest I can come. – Swanand Pangam May 24 '18 at 18:42
  • 1
    @SwanandPangam: No. First off, stop thinking about "lines". Lines are not a thing in C#. The body of a method consists of zero or more *statements*. An *expression statement* is a kind of statement. An expression statement has the form `expression;`, but the *expression* is required to be an increment, decrement, and so on. If you try to write what looks like an expression statement, but is not legal because its the wrong kind of expression, then the error is produced. – Eric Lippert May 24 '18 at 18:46
  • @SwanandPangam: The rule is "only certain kinds of expressions can be used in a statement of the form `expression;`". Your mistake was concluding from that rule that *there is only one kind of statement*. That's not a valid conclusion. There are lots of valid statement forms. They are forms other than `expression;`. The rule about what are legal expressions in that kind of statement do not apply to the rules about other kinds of statement! – Eric Lippert May 24 '18 at 18:49
  • @SwanandPangam: But the larger problem is that you are doing something very wrong if you are reading error messages trying to deduce rules of the language. That's not what the error messages are for: they are not for commenting on what makes a legal program. They are for helping people diagnose why illegal programs are illegal! If you want to know what makes a valid program then don't read the error messages, **read the language specification**. It's 800 pages of careful description of what makes a program legal. Read it! – Eric Lippert May 24 '18 at 18:51
  • Actually I was learning from learn.microsoft.com and tying to implement it in code. Now onwards, I will go through the language specification. Thanks – Swanand Pangam May 24 '18 at 19:03
  • I swear I've seen `await` in these error messages before. For example see https://stackoverflow.com/questions/17820277/only-assignment-call-increment-decrement-await-and-new-object-expressions-c – Neme May 26 '18 at 01:10
  • Is it possible `await` was added in the old compiler but not Roslyn? – Neme May 26 '18 at 01:10