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

时间:2014-06-17 13:07:06

标签: c# loops compiler-construction declaration

请考虑以下代码:

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在声明时应该再次为假。

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

有人在乎解释吗?

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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));

之类的东西告诉

答案 2 :(得分:1)

C# spec表示局部变量的范围限定在for语句中,但是,您可能会发现编译器在所有迭代中重复使用相同的变量作为优化而不是每次创建/丢弃相同的var。

话虽如此,如果您没有明确设置默认值,那么b在下一次迭代中实际上不会重置回false是有意义的。如果您为b设置了默认值,那么您应该会发现您的代码按预期工作,实际上 应该给它一个默认值。依靠默认值不是一个好主意,因为这些可以改变。

明确的声明可以提高清晰度并提高可读性。

答案 3 :(得分: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 */
    }
}