如何在c#中引用作用域外的变量
本文关键字:作用域 变量 引用 | 更新日期: 2023-09-27 18:04:56
教授让我们编写一个程序,输入用户的身高和体重,然后计算bmi。我决定更进一步,添加一些"输入验证"逻辑。这意味着,如果有人输入"cat"作为他们的体重,它会让用户知道"cat"不是有效的体重。
class MainClass
{
public static void Main ()
{
float userWeight;
float userHeight;
bool weight = true;
Console.Write ("Weight: ");
while (weight)
{
var inputWeight = (Console.ReadLine ());
if (!float.TryParse (inputWeight, out userWeight)) {
Console.WriteLine ("Invalid input");
Console.Write ("Please try again: ");
}
else
{
weight = false;
}
}
bool height = true;
Console.Write ("Height: ");
while (height)
{
var inputHeight = (Console.ReadLine ());
if (!float.TryParse (inputHeight, out userHeight)) {
Console.WriteLine ("Invalid input");
Console.Write ("Please try again: ");
}
else
{
height = false;
}
}
float bmiHeight = userHeight * userHeight; // error for userHeight
float bmi = userWeight / bmiHeight * 703; // error for userWeight
Console.WriteLine ("You BMI is " + bmi);
}
}
我得到的错误是"使用未分配的局部变量.."。我知道我在IF语句中分配了用户变量,并且它们只会持续到IF语句结束。
我的问题是,我如何在if语句中分配一个变量,然后在该语句之外引用该变量的新值?
当然我不需要把它们都嵌套,因为那样看起来很乏味....
这里的问题是,您的变量userHeight
和userWeight
仍然有可能持有垃圾值,因为您没有初始化它们。
你可以尝试用一个默认的有效值来初始化它们:
float userHeight = DEFAULT_HEIGHT;
float userWeight = DEFAULT_WEIGHT;
Do ... while(condition)
更适合您的情况,也允许编译器确认实际分配的值:
var isHeightValid = false;
do
{
var inputHeight = (Console.ReadLine ());
if (!float.TryParse (inputHeight, out userHeight)) {
Console.WriteLine ("Invalid input");
Console.Write ("Please try again: ");
}
else
{
isHeightValid = false;
}
}
while (!isHeightValid);
为什么:编译器不够聪明,不能确定while(condition)
的第一次迭代在一般情况下总是被执行,所以它假设while
中的代码可能不会运行,因此变量不会被赋值。是的,在您的特殊情况下,实际上可以检测到第一次迭代运行,但很可能这种情况并不常见,不足以向编译器添加规则。
do ... while
保证至少发生一次迭代,因此从编译器的角度来看,变量赋值(通过out
参数)总是会发生。
public void heightAndWeight()
{
double height = getValue("What is your height in inches?",36,80);
double weight = getValue("What is your weight in kilograms?",45,135);
if (height > 0 && weight > 0)
{
Console.WriteLine("your BMI is " + (height * weight).ToString("N2"));
}
}
private double getValue(string question,int lowRange,int highRange) {
double ret = 0;
while(ret==0){
Console.WriteLine(question);
string retStr = Console.ReadLine();
if(double.TryParse(retStr,out ret))
{
if(ret<lowRange||ret>highRange){
Console.WriteLine("You must enter a value between "+lowRange.ToString()+" and "+highRange.ToString()+". Please try again.");
ret=0;
}else{
return ret;
}
}else{
Console.WriteLine("Invalid entry. Please try again");
}
}
return ret;
}
为什么不初始化一些变量,例如,负值;除非用户插入有效值,否则代码不会结束
满足您的请求将破坏局部作用域的目的。这样做没有充分的理由。局部声明变量的目的是不让更广泛的作用域受到干扰。在您的情况下,它不是噪音,您的userWidth和userHeight变量在主作用域中有意义,因为您在那里使用它们。你要么在方法中初始化它们要么在if中声明它们并将使用它们的代码也移到if部分中。后者意味着您有一些双重代码,您可以通过将BMI的计算移动到一个单独的方法中并从两个if部分中调用该方法,将变量作为参数传递并返回BMI来解决这个问题。
将计算和输出语句放在同一个方法中并不好。但那是另一个故事了