繁体   English   中英

如何在C#中引用超出范围的变量

[英]How to reference a variable outside of scope in C#

我的教授要求我们创建一个吸收用户身高和体重的程序,然后计算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语句中分配变量,然后在该语句之外引用该变量的新值?

当然,我不必全部嵌套,因为这似乎很乏味。

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;
    }

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参数)。

这里的问题是,由于您没有初始化变量userHeightuserWeight它们仍有可能保持垃圾值。

您可以尝试使用默认有效值初始化它们:

float userHeight = DEFAULT_HEIGHT;
float userWeight = DEFAULT_WEIGHT;

您为什么不想要使用一些负值来初始化变量,例如? 除非用户插入有效值,否则您的代码将无法结束

满足您的要求将无法达到本地范围的目的。 这样做不能有充分的理由。 在本地声明变量的目的是不要在更大范围内产生噪音。 就您而言,这不是噪音,您的userWidth和userHeight变量在主作用域中具有含义,因为您在此处使用了它们。 因此,您可以在方法中正确地对其进行初始化,或者在if中声明它们,并将使用它们的代码也移至if部分。 后者将意味着您有一些双重代码,可以通过将BMI的计算移到单独的方法并在两个if部分中调用该方法,将变量作为参数传递并返回BMI来解决。

将计算和输出语句放在同一方法中将是不好的。 但这是另一个故事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM