we can do:
using (Stream s ..)
and:
for (int i ...)
why can't we as well do something like:
while ((int i = NextNum()) > 0) {..}
i find it very useful and sensible.
we can do:
using (Stream s ..)
and:
for (int i ...)
why can't we as well do something like:
while ((int i = NextNum()) > 0) {..}
i find it very useful and sensible.
Because then it's defined in every iteration. A for loop doesn't do that. (So you cant define it again after the first loop. Since it already exists.)
I'm not a language designer, but I'll give it an educated guess.
The clause inside the while()
is executed every single time the loop is executed. (+1 more time at the end.) The statement int i = NextNum()
declares a local variable. You can't declare a local variable more than once.
Semantically, it makes sense that this should be possible. In fact, as pointed out in the comments, this is possible in other languages. However, this would not be possible in C# without re-writing some major syntax rules.
Local variables must be declared in a statement. I believe the language to be separated this way because a variable declaration is not really executed. When you see a line of code that creates a variable and assigns it a value, that is actually just a shortcut for two statements. From the ECMA-334 Specification:
The example
void F() {
int x = 1, y, z = x * 2;
}
corresponds exactly to
void F() {
int x; x = 1;
int y;
int z; z = x * 2;
}
The variable declaration part by itself is not "executed". It just means that there should be some memory allocated on the stack for a certain type of variable.
The while
statement is expecting a boolean expression, but an expression cannot be composed of a statement -- without a special casing some new grammar.
The for
loop is specially designed to declare a local variable, but you'll note that declaration part is "executed" only once.
The using
statement was specifically designed to declare local variables (and dispose of them). It is also "executed" only once.
Also consider that a local variable declaration doesn't return a value -- it can't since the it allows you to declare multiple variables. Which value would this statement return?
int x = 1, y, z = x * 2;
The above statement is a local-variable-declaration. It is composed of a type, and three local-variable-declarators. Each one of those can optionally include an "=" token and a local-variable-initializer To allowing a local variable to be declared in this manner would mean that you pull apart the existing grammar a bit since you would need the type specifier, but mandate a single declarator so that it could return a value.
Enabling this behavior may nave negative side effects also, Consider that the while
and do
/while
statements are opposite, but parallel. As a language designer, would you also enable the do
statement to declare a local variable? I don't see this as possible. You wouldn't be able to use the variable in the body of the loop because it wouldn't have been initialized yet (as of the first run). Only the while statement would be possible, but then you would destroy the parallelism between while
and do
statements.
Don't know for certain but here is my educated guess.
The for case works because it actually has 3 parts.
These 3 run differing amounts of times. #1 runs only once, #2 runs number of iterations +1 and #3 runs once per iteration. Since #1 runs only once it's a nice and clean place to define a variable.
Now lets examine the while loop. It only has 1 part and it runs every iteration + 1. Since it runs every single time it's not a great place to define a variable which must necessarily be a part of the condition. It raises questions like
I'm guessing the complexity / ambiguity is one of the reasons why it's not allowed. That and it's probably never been high on the priority list.
There's no inherent reason why it couldn't be done - the C# designers just chose not to allow it. It works just fine in Perl, for example ("while ((my $i = NextNum()) > 0) { ... }").
As opposite to the 'for' loop, 'while' doesn't have a initialization part. The 'for' syntax looks like this:
for ( initializer; conditional expression; loop expression)
{
statements to be executed
}
and the 'while' looks like this:
while (condition)
{
statements to be executed
}
The closest thing to your request is:
int i;
while ((i = NextNum()) > 0) { ... }
Variable declarations are statements; the while loop expects an expression (an expression can be a statement, but not the other way around). using
and for
, on the other hand, are special-cased to allow variable declarations.
More importantly, the scope of such a thing would be unclear. Consider:
int x;
// ...
y = (int x = 42) + x;
// what is y?
Or worse:
(int x = 42) + (int x = 42);
Or even:
(int x = 42, y = 24) // what is the value of this expression?
Once you allow declarations be expressions, you have to deal with these things. In particular, the last example becomes a problem because it's hard to disambiguate between expression-declaration-as-a-statement or statement-declaration, so the expression style will have to be general enough to be how we do statement declarations.
This is starting to get to be a bit of a hairy design challenge, and since it's not really a very important feature, it's likely the C# committee decided not to allow declarations be expressions (or they simply never thought of it :).
Finally, you can actually get what you want with just a for
loop. For example:
while ((int i = NextNum()) > 0) {..}
// becomes...
for (int i; (i = NextNum()) > 0; ) {..}
// or...
for (int i = NextNum(); i > 0; i = NextNum()) {..}