为什么我们不能在while循环中定义变量?

时间:2009-10-17 03:59:10

标签: c# syntax

我们可以这样做:

using (Stream s ..)

for (int i ...)

为什么我们不能这样做:

while ((int i = NextNum()) > 0) {..}

我发现它非常有用和明智。

6 个答案:

答案 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 允许以这种方式声明局部变量意味着你将现有的语法分开一点,因为你需要类型说明符,但要求一个声明符,以便它可以返回一个值。

启用此行为也可能会产生负面影响,请考虑whiledo / while语句相反,但并行。作为语言设计者,您是否还要启用do语句来声明局部变量?我不认为这是可能的。您将无法在循环体中使用该变量,因为它尚未初始化(从第一次运行开始)。只有while语句才有可能,但是你会破坏whiledo语句之间的并行性。

答案 1 :(得分:9)

不确定,但这是我受过教育的猜测。

for case有效,因为它实际上有3个部分。

  1. 迭代变量
  2. 终止条件
  3. 增量
  4. 这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循环需要一个表达式(表达式可以是一个语句,但不是相反)。另一方面,usingfor是特殊的,允许变量声明。

更重要的是,这种事情的范围还不清楚。考虑:

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()) {..}