在为其赋值的if-else语句中使用未赋值的局部变量

本文关键字:赋值 局部变量 if-else 语句 | 更新日期: 2023-09-27 18:08:00

我有以下代码将一些字符串解析为双精度

double number;
double exponent;
if(!double.TryParse(line1, out number) &&
   !double.TryParse(line2, out exponent))
   throw new ArgumentException("Invalid string");
else
   number *= 10.0 * exponent;

我得到一个错误的编译器,exponent正在使用时,它没有分配(使用未分配的局部变量'指数')。但是,即使以相同的方式处理number变量,我也没有得到错误。此外,在if语句中调用的函数中,&&out指示符相结合,几乎可以保证在到达else块时,数字和指数都被赋值。

下面的代码可以编译。

double number;
double exponent;
if(!double.TryParse(line1, out number))
    throw new ArgumentException("Invalid string");
else{
    if(!double.TryParse(line2, out exponent)){
        throw new ArgumentException("Invalid string");
    }else{
        number *= 10.0 * exponent;
    }
}

为什么会这样?在第一个代码示例中,两个变量不是保证在执行else语句时被赋值吗?这两个代码示例在逻辑上不是等价的吗?这是编译器的限制吗?实际上,我有点惊讶编译器足够聪明,能够在第一个地方识别出底部代码示例中的情况。

在为其赋值的if-else语句中使用未赋值的局部变量

我很确定你想要||而不是&&。目前,只有当行都无效时才会抛出异常——如果第一行有效,则永远不会解析第二行。我假设你实际上只想使用numberexponent,如果它们都是有效的…

所以你的代码应该是(更习惯的格式):
if (!double.TryParse(line1, out number) || !double.TryParse(line2, out exponent))
{
    throw new ArgumentException("Invalid string");
}
else
{
    number *= 10.0 * exponent;
}

或者为了使整个事情更容易理解,减少涉及的否定的数量-显示如果所有都有效,您想要做什么,并处理else中的否定情况:

if (double.TryParse(line1, out number) && double.TryParse(line2, out exponent))
{
    number *= 10.0 * exponent;
}
else
{
    throw new ArgumentException("Invalid string");
}

&&短路,因此如果number的解析失败,第二个TryParse将永远不会执行,因此exponent可以不初始化。

旁注-如果解析失败,您希望失败,所以您真正想要的是OR (|)而不是AND (&)

一些选择:

  • &&更改为||以修复逻辑错误
  • 颠倒逻辑,将"happy case"放在前面:

    double number;
    double exponent;
    // you can use "&&" here because you don't reference exponent unless both parses succeed.
    if(double.TryParse(line1, out number) &&
       double.TryParse(line2, out exponent))
    {
       number *= 10.0 * exponent;
    }
    else
       throw new ArgumentException("Invalid string");
    

不行,因为在上面的例子中,number和exponent都必须为空才能到达不可破坏的路径:

如果(!双

。TryParse(line1, out number) &&双。TryParse(line2, out exponent))

this也不会编译:

如果(!双

。TryParse(line1, out number) ||双。TryParse(line2, out exponent))

因为如果行失败(不是数字),那么在初始化exponent之前,您将退出if语句。你的第二个IF语句是正确的方法。