不能在do/while循环中声明的while子句中使用变量
本文关键字:while 子句 变量 声明 循环 不能 do | 更新日期: 2023-09-27 18:10:38
为什么我不允许使用我在do
内声明的变量,并在do/while循环的while
部分内使用它?
do
{
index += index;
int composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite)); // cannot resolve symbol composite
第一次看到这个,我以为是编译器的bug。所以我重新启动了Visual Studio多次,但它仍然不识别while
中的变量。
代码有什么问题,还是这是编译器的错误?
你的变量是在do/while之外使用的(在c#中,通常是用括号定义范围),因为它是在do-while内部声明的,所以你不能在该范围之外使用它。
你可以通过简单地在循环外声明它来解决这个问题。
int composite = 0; // you are not required to set it to zero, as long
// as you do not use it before you initialize it
do
{
index += index;
composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
注意(1),通常的做法是一次声明和设置一个变量,但这不是必需的,只要你在使用它之前设置它。
注释(2):在c#中,花括号{....}
定义了变量的作用域。你不能在它的作用域之外使用一个变量,它不再是"可见的",事实上,一旦它超出了作用域,它就准备被垃圾收集,它的内容可以是未定义的。
我知道这个,但是为什么编译器不能这样做
你在评论里问了这个问题。答案并没有看起来那么简单。这在很大程度上取决于语言的定义。有些语言,如Perl或较老的BASIC,允许在任何级别和任何范围内声明变量。其他语言允许变量的作用域,并要求在使用变量之前声明变量(c#, Java, c++, Python)。通常(但不一定),这在静态类型语言中很常见,因为编译器需要事先知道要在变量中放入什么类型的数据,以便进行类型检查。
如果编译器强制声明,但不强制作用域,这意味着所有变量都是全局的,这在大型程序中很难做到,因为作为程序员,您必须维护在哪里使用了哪些变量名并保持唯一性。这非常乏味(想想COBOL)。
c#添加了dynamic
关键字,它允许变量具有动态类型,但这仍然要求您在使用变量之前定义该变量。编译器可以做到这一点,但是c#的设计者认为清晰的语言更好,在他们看来,声明变量是一件好事,因为它可以防止虚假错误和无法跟踪的代码:
// can you see the problem?
va1l = 1;
val1 = 2;
vall = va1l + vall;
这不是一个bug。while
循环中的条件在定义变量的块之外。
int composite;
do
{
index += index;
composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
这个变量的作用域就在循环内部....不能在循环外使用
你应该这样做....
int composite;
do
{
index += index;
composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
当{ ... }
表示代码块时,该块中的所有变量都被限制在该特殊范围内。你的条件在这个范围之外,所以它不能访问那里的变量。在循环外声明它,它就能工作了:
int composite = 0;
do
{
index += index;
composite += index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
根据规范,do .. while
的条件变量应该在循环外声明,否则在每次迭代中该变量都会被重新初始化,这是没有意义的。
int composite;
do
{
index += index;
composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
更多一般规则:你不能使用其作用域之外的变量在c#中是{...}
,例如
{
int x = 123;
...
}
x = 456; // <- compile time error
代码中的 do {} while
仅仅意味着作用域属于循环。
我明白,虽然"是否在块之外,但是考虑一下:
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
这里,变量"i"是块作用域(在for's块之外不可见),实际上是一个新的instance"在每次循环迭代时创建。但是实际的定义在代码块之外。
你可以说"for"声明属于代码块,但之后我会写上&;while&;也属于块。这就是不一致!
int composite;
do
{
index += index;
composite = index + 1;
// more code here
} while (UnsetBitmask(bitmasks, composite));
如果您真的不想将变量声明移到循环体之外(正如所有答案所建议的那样),还有另一种(非常明显但非常丑陋的)解决方法:
do
{
index += index;
int composite = index + 1;
// more code here
// check the condition inside the loop body, where the variable exisits
if(!UnsetBitmask(bitmasks, composite)) break;
} while (true);