代码之家  ›  专栏  ›  技术社区  ›  abatishchev Karl Johan

一次或多次未分配的局部变量?

  •  2
  • abatishchev Karl Johan  · 技术社区  · 15 年前

    我有下一个代码:

      static void Main(string[] args)
      {
         byte currency;
         decimal amount;
         if (Byte.TryParse("string1", out currency) && Decimal.TryParse("string2", out amount))
         {
            Check(currency, amount);
         }
         Check(currency, amount); // error's here
      }
    
      static void Check(byte b, decimal d) { }
    

    然后得到下一个错误:

    使用未分配的局部变量 “数额”

    为什么我要得到它,这是合法的,为什么只有 amount ?为什么? currency 在这种情况下,分配和 数量 -不是吗?

    4 回复  |  直到 15 年前
        1
  •  2
  •   Aaronaught    15 年前

    看这条线(我把它分成两行):

    if (Byte.TryParse("string1", out currency) &&
        Decimal.TryParse("string2", out amount))
    

    这个 && 运算符是 短路 评估,这意味着如果第一个 Byte.TryParse 不成功,那么第二个 Decimal.TryParse 永远不会被处决。

    currency 将始终分配,因为 TryParse 设置 out currency 如果解析失败,则引用默认值。然而, amount 在这种情况下仍然是未定义的。就好像你写了这样的代码:

    if (Byte.TryParse("string1", out currency))
    {
        if (Decimal.TryParse("string2", out amount))
        {
            Check(currency, amount);
        }
    }
    Check(currency, amount);
    

    这应该让事情变得更加明显。第一个里面的部分 if 语句总是被执行并将值赋给 货币 . 里面的部分 第二 嵌套的 如果 只有第一个语句成功时,才会执行该语句。否则, 数量 当你击中第二个时就没有价值了 Check .

    如果要使用默认值, 货币 无法分析,然后将局部变量初始化为默认值:

    byte currency = 0;
    decimal amount = 0;
    if (Byte.TryParse("string1", out currency) &&
        Decimal.TryParse("string2", out amount))
    {
    // Etc.
    

    或者,您可以简单地分析这两种方法,如@martin所说。

        2
  •  1
  •   Rick Mogstad    15 年前

    这只是一个编译器警告,旨在防止您使用未分配的变量(尽管我认为您理解这一点)。我无法解释为什么只有在使用一个未赋值变量而不是另一个变量时才能得到它。

        3
  •  1
  •   Hans Passant    15 年前

    C语言规范的第5.3章对此进行了讨论。这是一个有力的章节,但我相信编译器也应该为未分配的“currency”变量发出错误。如果您注释掉if()语句并阻塞它,那么现在编译器会突然变聪明。即使“货币”从未在注释代码中使用过。

    那不可能是对的,我想你发现了一个虫子。如果Eric Lippert没有经过,您可以在connect.microsoft.com上报告该错误。

        4
  •  0
  •   M4N    15 年前

    这是因为程序中有一个路径,编译器无法保证 amount 分配初始值:当第一个 TryParse() 失败。这就是为什么你在尝试使用的线路上会出现错误的原因。 数量 .

    From MSDN:

    作为out参数传递的变量不需要初始化。但是,在方法返回之前,必须为out参数赋值。

    您可以通过为局部变量指定默认值来解决此问题:

     decimal amount = 0;
    

    否则你必须确保 TyPARSESS() 在任何情况下都会进行呼叫,例如(不是很好的代码):

    bool b1 = Byte.TryParse("string1", out currency);
    bool b2 = Decimal.TryParse("string2", out amount);
    
    if (b1 && b2) {...}
    

    btw:这个代码片段也会产生相同的编译器错误,因为 a 未分配值:

    int a, b=1;
    int c = a+b;