在分配它的if-else语句中使用未分配的局部变量

时间:2015-08-13 17:39:03

标签: c# parsing compiler-errors

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

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在未分配时使用(使用未分配的局部变量'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语句时分配?两个代码示例在逻辑上是否等效?这是编译器的限制吗?实际上,我很惊讶编译器足够聪明,可以在底部代码示例中识别出这个案例。

3 个答案:

答案 0 :(得分:6)

我很确定您需要||而不是&&。目前,如果两个行无效,则只会抛出异常 - 如果第一行有效,则您甚至不会解析第二行。我假设您实际上只想使用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");
}

答案 1 :(得分:3)

&&短路,因此如果解析number失败,则第二个TryParse将永远不会执行,因此exponent可能会保持未初始化状态。

附注 - 如果要么解析失败,你想要失败,所以你真的想要OR(|)而不是AND(&

一些选项:

  • &&更改为||以修复逻辑错误
  • 颠倒逻辑,将“快乐案例”放在第一位:

    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");
    

答案 2 :(得分:0)

不,因为在你的顶级示例中,number和exponent都必须为null才能到达不可破坏的路径:

if(!double.TryParse(line1,out number)&&    !double.TryParse(line2,out exponent))

这将无法编译:

if(!double.TryParse(line1,out number)||    !double.TryParse(line2,out exponent))

因为如果行失败(不是数字),那么在初始化exponent之前,你将摆脱IF语句。你的第二个IF声明是正确的做法。