使用未初始化的变量-编译器已损坏
本文关键字:编译器 已损坏 变量 初始化 | 更新日期: 2023-09-27 18:26:09
很明显,标题有点开玩笑,但我已经检查了一遍又一遍,我看不到逻辑中的错误。
编译器抱怨变量parsed
可能未在return语句中初始化。我不同意。我们谁错了,为什么?
public DateTime? Test(string nextDate)
{
DateTime parsed;
if (nextDate != "TBC" && !DateTime.TryParse(nextDate, out parsed))
{
throw new Exception();
}
if (nextDate == "TBC")
return null;
return parsed;
}
编译器不应该告诉
if (nextDate != "TBC")
和
if (nextDate == "TBC")
相互排斥。它没有试图在这两种情况之间建立任何联系。因此,如果你到达return parsed;
,它不能说你肯定已经呼叫了DateTime.TryParse(nextDate, out parsed)
。
基本上,编译器遵循相对简单的规则来确定确定赋值(和可达性)。简单的规则很容易推理,很容易实现,也很容易编写代码
幸运的是,您可以使代码更简单和使其同时编译:
public DateTime? Test(string nextDate)
{
if (nextDate == "TBC")
{
return null;
}
DateTime parsed;
if (!DateTime.TryParse(nextDate, out parsed))
{
throw new Exception();
}
return parsed;
}
现在,我们在一个位置的开头处理"TBD"的"特殊情况",然后我们可以在代码的其余部分忽略该特殊情况,并无条件调用TryParse
,使parsed
明确指定。
如果是nextData == "TBC"
,则不会调用TryParse
,因为整个条件无论如何都不可能为true。因此,parsed
可能不会被初始化。
你们两个都是对的。
未初始化变量检查的逻辑着眼于所有可能的控制流路径,而不进行更深入的逻辑分析。编译器的这一部分并不关心nextDate == "TBC"
和nextDate != "TBC"
从来都不是真的。所以编译器是正确的从他的PoV。
你不想在编译器中对程序逻辑进行太深入的分析。你想要简单易懂的规则。在复杂的情况下,编译器基本上需要在编译时使用所有可能的输入值来运行整个程序,以确定变量是否初始化。
你是对的,因为你知道条件会解决的,所以如果不初始化变量,就永远无法使用它。
我会这样重写你的函数:
public DateTime? Test(string nextDate)
{
DateTime parsed;
if (nextDate == "TBC" )
return null;
if(!DateTime.TryParse(nextDate, out parsed))
throw new Exception();
return parsed;
}
但是,由于您无论如何都会抛出异常,您可能希望使用Parse
而不是TryParse
。
因为out是if语句的一部分,您必须初始化该值。
因为如果满足从左到右,在您的情况下,nextDate != "TBC"
首先得到验证,然后检查下一个语句。
所以这就像
if( fist check)
{
if(second check)
{
}
}