为什么我未初始化的变量在 TryParse 中设置了它的值后再次变为未分配?
Why does my uninitialised variable become unassigned again after it has its value set inside of TryParse?
变量 inputBool 在 while 循环外声明,然后在我尝试将 userInput 解析为布尔值时在 while 循环内设置。但是,一旦退出 while 循环,inputBool 将再次变为未声明状态!
但是,如果我用一个值 (EG false) 初始化 inputBool 变量,它将在 while 循环内部设置,然后将保持设置为在 TryParse 内部分配给它的任何值,即使在 while 循环退出后也是如此.
这是我想要的行为,但为什么当我不立即初始化变量时它不起作用?
foreach (string question in questions)
{
bool isBool = false;
// inputBool declared here.
bool inputBool;
string userInput;
while (!isBool)
{
Console.WriteLine(question);
userInput = Console.ReadLine();
// inputBool gets assigned a value here in the TryParse.
isBool = Boolean.TryParse(userInput, out inputBool);
if (!isBool) Console.WriteLine("Please respond with 'true' or 'false'.");
}
// inputBool is unassigned here!
answers[askingIndex] = inputBool;
askingIndex++;
}
从流程分析的角度来看,无法保证 while
循环至少会执行一次。当然,您知道其他情况,因为您的条件涉及一个初始化为值 false
的 bool
变量,但编译器不够智能,无法实现它。
因此,如果它至少没有执行一次,inputBool
仍然会在最后被初始化,因此会出错。
您需要确保变量在所有 代码路径中初始化。有两种可能的修复方法:
- 将
while
更改为 do...while
。那个保证至少执行一次,这确保变量被初始化。
- 将变量初始化为合理的默认值。
C# 语言definite-assignment 分析仅使用程序结构,不使用数据值。
一个密切相关的问题:
bool b = f();
int x;
// (1)
if (b) {
x = 42;
// (2)
Trace.WriteLine(x); // ok
}
// (3)
if (b) {
// (4)
Console.WriteLine(x); // error, use of potentially unassigned variable x
}
在 (1) 处很明显,x 可能未分配(当然,偶数)。在 (2) 处,x 已明确分配。在 (3) 处,当且仅当 b 为真时 x 才被赋值……但编译器不会尝试跟踪这一点。它只是说“可能未分配”。结果在 (4) 处,编译器无法证明 x 已明确赋值,即使你我可以。
当编译器遇到 while 循环时,可以跳过该循环。因此,循环之前可能未分配的任何内容在循环之后仍可能未分配。即使你和我可以证明 你的 循环仅在变量被赋值时终止,这取决于数据值,而不是结构,并且 C# 不考虑它。
通过制作代码流程图,您可以非常轻松地重新创建编译器的明确赋值分析。在两条路径结合的任何一点,将布尔值 AND 应用于变量的状态。
变量 inputBool 在 while 循环外声明,然后在我尝试将 userInput 解析为布尔值时在 while 循环内设置。但是,一旦退出 while 循环,inputBool 将再次变为未声明状态!
但是,如果我用一个值 (EG false) 初始化 inputBool 变量,它将在 while 循环内部设置,然后将保持设置为在 TryParse 内部分配给它的任何值,即使在 while 循环退出后也是如此.
这是我想要的行为,但为什么当我不立即初始化变量时它不起作用?
foreach (string question in questions)
{
bool isBool = false;
// inputBool declared here.
bool inputBool;
string userInput;
while (!isBool)
{
Console.WriteLine(question);
userInput = Console.ReadLine();
// inputBool gets assigned a value here in the TryParse.
isBool = Boolean.TryParse(userInput, out inputBool);
if (!isBool) Console.WriteLine("Please respond with 'true' or 'false'.");
}
// inputBool is unassigned here!
answers[askingIndex] = inputBool;
askingIndex++;
}
从流程分析的角度来看,无法保证 while
循环至少会执行一次。当然,您知道其他情况,因为您的条件涉及一个初始化为值 false
的 bool
变量,但编译器不够智能,无法实现它。
因此,如果它至少没有执行一次,inputBool
仍然会在最后被初始化,因此会出错。
您需要确保变量在所有 代码路径中初始化。有两种可能的修复方法:
- 将
while
更改为do...while
。那个保证至少执行一次,这确保变量被初始化。 - 将变量初始化为合理的默认值。
C# 语言definite-assignment 分析仅使用程序结构,不使用数据值。
一个密切相关的问题:
bool b = f();
int x;
// (1)
if (b) {
x = 42;
// (2)
Trace.WriteLine(x); // ok
}
// (3)
if (b) {
// (4)
Console.WriteLine(x); // error, use of potentially unassigned variable x
}
在 (1) 处很明显,x 可能未分配(当然,偶数)。在 (2) 处,x 已明确分配。在 (3) 处,当且仅当 b 为真时 x 才被赋值……但编译器不会尝试跟踪这一点。它只是说“可能未分配”。结果在 (4) 处,编译器无法证明 x 已明确赋值,即使你我可以。
当编译器遇到 while 循环时,可以跳过该循环。因此,循环之前可能未分配的任何内容在循环之后仍可能未分配。即使你和我可以证明 你的 循环仅在变量被赋值时终止,这取决于数据值,而不是结构,并且 C# 不考虑它。
通过制作代码流程图,您可以非常轻松地重新创建编译器的明确赋值分析。在两条路径结合的任何一点,将布尔值 AND 应用于变量的状态。