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

我们可以做的:

using (Stream s ..) 

和:

 for (int i ...) 

为什么我们不能这样做:

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

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

我不是语言设计师,但我会给它一个有根据的猜测。

每次执行循环时都会执行while()内的子句。 (最后+1次。)语句int i = NextNum()声明一个局部变量。 您不能多次声明局部变量。

更新

从语义上讲,这应该是可行的。 事实上,正如评论中所指出的,这在其他语言中是可能的。 但是,如果不重写一些主要的语法规则,这在C#中是不可能的。

必须在语句中声明局部变量。 我相信这种语言是这样分开的,因为变量声明并没有真正执行。 当您看到一行代码创建变量并为其赋值时,这实际上只是两个语句的快捷方式。 来自ECMA-334规范 :

这个例子

 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; 

上述语句是一个局部变量声明 。 它由一个类型和三个局部变量声明符组成 。 其中每一个都可以选择包含一个“=”标记和一个局部变量初始化器 。允许以这种方式声明局部变量意味着你需要稍微拆分现有的语法,因为你需要类型说明符,但是强制要求一个声明者,以便它可以返回一个值。

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

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

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

  1. 迭代变量
  2. 终止条件
  3. 增量

这3次运行的次数不同。 #1只运行一次,#2运行迭代次数+1和#3每次运行运行一次。 因为#1只运行一次,所以它是一个定义变量的好地方。

现在让我们来看看while循环。 它只有1个部分,它每次迭代运行+ 1.由于它每次都运行,因此它不是定义变量的好地方,变量必须是条件的一部分。 它提出了类似的问题

  • 定义是每次迭代发生一次还是一次? 如果是后者,有多少人会误解这个并搞砸了条件? 如果它是前者那么你有一个完整的声明,其中每个查询只执行一次部分
  • 多变量定义如何表现?

我猜测复杂性/含糊不清是其不被允许的原因之一。 在优先级列表中,它可能永远不会很高。

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

因为它在每次迭代中定义。 for循环不会这样做。 (所以你不能在第一个循环之后再次定义它。因为它已经存在。)

没有固有的原因导致它无法完成–C#设计师只是选择不允许它。 它在Perl中运行得很好,例如(“while((my $ i = NextNum())> 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()) {..}