【问题标题】:Variables retain their value in a loop?变量在循环中保留其值?
【发布时间】:2022-01-24 00:32:52
【问题描述】:

如果我在控制台应用程序中运行这个简单的代码:

For i As Integer = 1 To 10
    Dim s As String = i.ToString()
    Dim x As Decimal
    If i = 1 Then
        x = Decimal.Parse(s)
    End If
    Console.WriteLine(x.ToString())
Next
Console.ReadLine()

出乎意料的是,x 保留了它的值 1,因此 1 被打印了 10 次。我认为循环的每次迭代都是它自己的代码块,并且状态没有延续?为什么会这样?我希望x 的默认值为System.Decimal

同样的事情发生在 C# 中,除了编译器不允许您在未初始化的变量上调用 ToString(),但如果您在 Visual Studio 中设置断点,您可以看到 x 保留其值 1。

for (int i = 1; i <= 10; i++)
{
    string s = i.ToString();
    Decimal x;
    if(i == 1)
    {
        x = Decimal.Parse(s);
    }
    // Value of x remains 1
}
Console.ReadLine();

【问题讨论】:

  • 你不需要ToString,只需使用Console.WriteLine(x)
  • 如果你想在每次迭代时初始化x,使用Dim x As Decimal = 0
  • 对于 C#,在循环中,当 i 等于 2 到 10 时,x 尚未被赋值。如果您能够编译和运行程序,则不能依赖 x 的值。当我尝试使用试图打印 x 的行来编译它时,我会收到一个编译错误,指出 x 的值未分配。
  • 按预期工作 -> 只有在 i = 1 时才更改 x 值,所以.... 有什么问题?

标签: c# .net vb.net


【解决方案1】:

关于 VB.NET 看一下作用域here。在“Block Scope”部分有一条说明如下:

即使变量的作用域被限制在一个块中,它的生命周期也是 仍然是整个过程。如果您输入的块超过 在此过程中,每个块变量都会保留其先前的 价值。为了避免在这种情况下出现意外结果,明智的做法是 在块的开头初始化块变量。

因此,这种行为是设计使然,您应该将变量初始化为代码所需的任何值。

我修改了您的代码以显示第一次 x 初始化为 0,但之后它保留了 1 的值。

    For i As Integer = 1 To 10
        Dim s As String = i.ToString()
        Dim x As Decimal
        Console.WriteLine(x.ToString())
        If i = 1 Then
            x = Decimal.Parse(s)
        End If

        Console.WriteLine(x.ToString())
    Next

    Console.ReadLine()

【讨论】:

    【解决方案2】:

    认为循环的每次迭代都是它自己的代码块,并且状态没有延续

    它确实“延续”。

    int i 的范围为循环的整个范围,值从 1 到 10。

    if 语句仅在第一次迭代时执行,x 被限定为 外部方法 的局部变量(假设进入循环),而不仅仅是循环体。话虽如此,在循环之后和循环之外,x == 1 也是如此。

    其实循环中的Decimal x;是多余的,和你的执行逻辑是一样的

    string s;
    Decimal x;
    for (int i = 1; i <= 10; i++)
    {
        s = i.ToString();
    
        if(i == 1)
        {
            x = Decimal.Parse(s);
        }
        Console.WriteLine(x);
    }
    // x still defined here
    

    【讨论】:

    • 您显示的代码与在循环内确定变量的范围相同。当变量在循环范围内时,代码不编译,因此您断言它的行为相同只是错误的。代码不能精确编译,因为变量 作用于它们所在的块,而不是整个方法。
    • 是的,但是如果我尝试在原始代码的循环之外访问x,则会出现编译错误“未声明变量”。如果我尝试访问在循环定义中的循环内声明的变量,它也不允许这样做。所以价值仍然存在是没有意义的......
    • 啊,这里来自MS:“即使一个变量的范围被限制在一个块中,它的生命周期仍然是整个过程的生命周期。如果你在这个过程中多次进入这个块过程中,每个块变量都保留其先前的值。为避免在这种情况下出现意外结果,明智的做法是在块的开头初始化块变量。在我看来仍然很愚蠢,但事实就是如此......
    • @OneCricketeer 似乎是对的。我已经用一些额外的行为测试了 VB 和 C# sn-ps,看看会发生什么,并且 Dim x As Decimal 确实表现得好像在循环外声明,尽管它是在循环内声明的。对于像我这样的 C# 开发人员来说,这很愚蠢,但事实就是如此。这是否符合我不知道的语言规范。
    • @John:是的,但是由于 C# 不允许您在变量未初始化时实际对变量执行任何操作,因此它实际上不是 C# 的“功能”。
    【解决方案3】:

    为了弄清楚你想要什么,它应该是这样的:

    For i As Integer = 1 To 10
        If i = 1 Then
          Console.WriteLine(Decimal.Parse(i.ToString()))
        End If
    Next
    

    这将为您提供您想要的相同结果,但它是可读的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-05
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-17
      • 1970-01-01
      相关资源
      最近更新 更多