循环中的变量声明不会重置为默认值

问题描述 投票:0回答:4

考虑以下代码:

for (int i = 0; i < 10; i++)
{
    bool b;          /* #1 */
    if (i == 0)
    {
        b = true;    /* #2 */
    }
}

我在#1#2处设置了断点。

第一次 (i = 0),b 在 #1 处设置为 false,在 #2 处设置为 true。

第二次 (i = 1),b 在 #1 处为真。

这对我来说没有意义,因为我假设在第二个循环(i = 1)中开始时,b 在声明时应该再次为 false。

我假设第二个循环中 #1 处 b = false。

有谁愿意解释一下吗?

c# loops declaration
4个回答
7
投票
您在调试器中看到的

b

 值无效。 C# 要求先初始化或分配所有局部变量,然后才能读取它们。因此,您在 Visual Studio 的调试器中看到的值是无用的,因为它无法读取。无法编写一段 C# 代码来“看到”该值在第二次迭代中设置为 
true
,因为编译器会将此类使用标记为无效:

for (int i = 0; i < 10; i++) { bool b; /* #1 */ Console.WriteLine(b); // <<== INVALID!!! This will not compile. // error CS0165: Use of unassigned local variable `b' if (i == 0) { b = true; /* #2 */ } }

如果向

false

 添加显式初始化,则上面的代码将编译。调试器也会在断点处显示 
false


2
投票
请注意,如果您尝试

for (int i = 0; i < 10; i++) { bool b; /* #1 */ if (!b) { i = 100000; } if (i == 0) { b = true; /* #2 */ } }

你会得到一个编译错误,因为变量必须在使用前初始化

但是为了你的好奇心......

如果您查看 IL,您会注意到 b 被声明为本地。

.maxstack 2 .locals init ( [0] int32 i, [1] bool b, [2] bool CS$4$0000 )

这意味着当方法加载到堆栈时就分配了堆栈空间。它使用的空间在方法执行期间不会改变,因此它不会重置

除非你用类似b = default(typeof(bool));

之类的东西告诉它


1
投票
C# 规范

规定局部变量的作用域是在 for 语句内,但是,您可能会发现编译器在所有迭代中重复使用相同的变量作为优化,而不是创建/丢弃每次都使用相同的变量。


话虽如此,假设您没有明确设置默认值,那么

b

实际上不会在下一次迭代中重置回

false
是有道理的。如果您为
b
设置了默认值,那么您应该会发现您的代码按预期工作,并且事实上您
应该
无论如何都给它一个默认值;依赖默认值不是一个好主意,因为这些可以更改。 显式声明更加清晰并提高可读性。


0
投票

bool b;

并且您没有为该声明的变量分配默认值,然后尝试在 if 条件块中为 
bool b;

分配值,这只会造成一些混乱。


因此,首先要避免这种混乱,您必须在声明变量后将值分配给声明的变量

bool b;

,这将使您清楚地了解默认值和您在循环中将来分配的值


喜欢

bool b = True; or bool b = False;


修改代码

for (int i = 0; i < 10; i++) { bool b = False; /* #1 */ if (i == 0) { b = true; /* #2 */ } }

	
© www.soinside.com 2019 - 2024. All rights reserved.