【问题标题】:Unassigned local variable in one time of several?一次未分配的局部变量?
【发布时间】:2010-02-18 22:05:04
【问题描述】:

我有下一个代码:

  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 而分配了amount - 不是?

【问题讨论】:

标签: c# .net struct unassigned-variable


【解决方案1】:

看看这一行(我分成两行):

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 语句中的部分总是被执行并为currency 赋值。 second 内的部分,嵌套的if 语句只有在第一个成功的情况下才会被执行。否则,当您点击第二个Check 时,amount 将毫无价值。

如果你想在currency无法解析的情况下使用默认值,那么只需将locals初始化为默认值:

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

或者您可以像@Martin 所说的那样简单地解析它们。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      C# 语言规范的第 5.3 章讨论了这一点。这是一个充实的章节,但在我看来,编译器确实应该为未分配的“货币”变量发出错误。如果您注释掉 if() 语句并阻止它会变得有趣,现在编译器突然变得聪明起来。尽管注释代码中从未使用过“货币”。

      这不可能,我认为你发现了一个错误。如果 Eric Lippert 没有通过,您可以在 connect.microsoft.com 上报告错误

      【讨论】:

      • 这不是错误。第一个 TryParse 将始终被执行并将 out arg 设置为默认值;如果第一个失败,第二个TryParse 将不会被执行,因此amount 的值可能未定义,但currency 的值不会。
      • 哎呀,你是对的。我没有看到使用不同输出参数的 TryParse 调用。
      • 如果您有什么想引起我注意的事情,您可以随时使用我博客上的联系链接。
      【解决方案4】:

      发生这种情况是因为您的程序中有一个路径,编译器无法保证为 amount 分配一个初始值:当第一个 TryParse() 失败时。这就是为什么您在尝试使用 amount 的行上出现错误的原因。

      From MSDN:

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

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

       decimal amount = 0;
      

      否则,您必须确保在任何情况下都进行了两个 TryParse() 调用,例如(不是很好的代码):

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

      顺便说一句:这段代码也会产生同样的编译错误,因为a 没有赋值:

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

      【讨论】:

      • @Martin:Struts 默认获得了它的价值,不是吗?
      • @Martin:我认为它在运行时根本不会失败,只是在 IDE 中作为警告。两个 TryParse 调用都应该失败,那么为什么只显示十进制的警告,而不是字节的呢?
      • @abatischev 啊,是的。默认情况下 C# 中的错误,VB 中的警告。只是IDE中的一个错误,对吧?如果您禁用该错误,我认为代码实际上会起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 2013-10-18
      • 2015-11-09
      • 2012-05-18
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多