我们可以这样做:
using (Stream s ..)
和
for (int i ...)
为什么我们不能这样做:
while ((int i = NextNum()) > 0) {..}
我发现它非常有用和明智。
答案 0 :(得分:14)
我不是语言设计师,但我会给它一个有根据的猜测。
每次执行循环时都会执行while()
内的子句。 (最后+1次。)语句int i = NextNum()
声明一个局部变量。您不能多次声明局部变量。
从语义上讲,这应该是可行的。事实上,正如评论中所指出的,这在其他语言中是可能的。但是,如果不重写一些主要的语法规则,这在C#中是不可能的。
必须在声明中声明局部变量。我相信这种语言是这样分开的,因为变量声明并没有真正执行。当您看到一行代码创建一个变量并为其赋值时,这实际上只是两个语句的快捷方式。来自ECMA-334 Specification:
示例
void F() {
int x = 1, y, z = x * 2;
}
完全对应
void F() {
int x; x = 1;
int y;
int z; z = x * 2;
}
变量声明部分本身不是“已执行”。它只是意味着应该在堆栈上为某种类型的变量分配一些内存。
while
语句需要一个布尔表达式,但表达式不能由语句组成 - 没有特殊的大小写一些新语法。
for
循环专门用于声明局部变量,但您会注意到声明部分仅“执行”一次。
using
语句专门用于声明局部变量(并处理它们)。它也只被“执行”一次。
还要考虑局部变量声明不返回值 - 它不能,因为它允许您声明多个变量。该陈述将返回哪个值?
int x = 1, y, z = x * 2;
上述声明是 local-variable-declaration 。它由一个类型和三个局部变量声明符组成。其中每一个都可以选择包含一个“=”标记和一个 local-variable-initializer 允许以这种方式声明局部变量意味着你将现有的语法分开一点,因为你需要类型说明符,但要求一个声明符,以便它可以返回一个值。
启用此行为也可能会产生负面影响,请考虑while
和do
/ while
语句相反,但并行。作为语言设计者,您是否还要启用do
语句来声明局部变量?我不认为这是可能的。您将无法在循环体中使用该变量,因为它尚未初始化(从第一次运行开始)。只有while语句才有可能,但是你会破坏while
和do
语句之间的并行性。
答案 1 :(得分:9)
不确定,但这是我受过教育的猜测。
for case有效,因为它实际上有3个部分。
这3次运行次数不同。 #1只运行一次,#2运行迭代次数+1和#3每次运行运行一次。因为#1只运行一次,所以它是定义变量的一个好的和干净的地方。
现在让我们检查一下while循环。它只有1个部分,它每次迭代运行+ 1.由于它每次都运行,因此它不是定义变量的好地方,变量必须是条件的一部分。它提出了像
这样的问题我猜测复杂性/含糊不清是其不被允许的原因之一。那可能从未在优先级列表中占据优势。
答案 2 :(得分:2)
与'for'循环相反,'while'没有初始化部分。 'for'语法如下所示:
for ( initializer; conditional expression; loop expression)
{
statements to be executed
}
和'while'看起来像这样:
while (condition)
{
statements to be executed
}
与您的请求最接近的是:
int i;
while ((i = NextNum()) > 0) { ... }
答案 3 :(得分:1)
因为它在每次迭代中定义。 for循环不会那样做。 (所以你不能在第一个循环之后再次定义它。因为它已经存在了。)
答案 4 :(得分:1)
没有固有的原因导致它无法完成--C#设计师只是选择不允许它。它在Perl中运行得很好,例如(“while((my $ i = NextNum())> 0){...}”)。
答案 5 :(得分:0)
变量声明是声明; while循环需要一个表达式(表达式可以是一个语句,但不是相反)。另一方面,using
和for
是特殊的,允许变量声明。
更重要的是,这种事情的范围还不清楚。考虑:
int x;
// ...
y = (int x = 42) + x;
// what is y?
或者更糟:
(int x = 42) + (int x = 42);
甚至:
(int x = 42, y = 24) // what is the value of this expression?
一旦允许声明为表达式,就必须处理这些事情。特别是,最后一个示例成为一个问题,因为很难消除expression-decla-as-a-statement或statement-declaration之间的歧义,因此表达式样式必须足够通用,以便我们进行语句声明。
这开始变得有点像一个毛茸茸的设计挑战,因为它不是一个非常重要的特性,很可能C#委员会决定不允许声明是表达式(或者他们根本就没想过:)
最后,您实际上只需for
循环即可获得所需内容。例如:
while ((int i = NextNum()) > 0) {..}
// becomes...
for (int i; (i = NextNum()) > 0; ) {..}
// or...
for (int i = NextNum(); i > 0; i = NextNum()) {..}