简体   繁体   中英

C# returning error “not all code paths return a value” - how to find the path not returning a value

I am very new to programming in general so I may be missing something very obvious. But still, which path leads to not returning a value?

public static int CheckAge()
        {
            int userAge; 
            bool inValidInput = true;
            while (inValidInput)
            {
                Console.Write("Enter your age: ");
                string stringAge = Console.ReadLine();

                if (int.TryParse(stringAge, out userAge))
                {
                    switch (userAge)
                    {
                        case int n when (n < 1 || n > 120):
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.Write("RANGE ");
                            Console.ForegroundColor = ConsoleColor.White;
                            Console.Write("error\n");
                            Console.Write("Accepted range are numbers (eg. 123) ");
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.Write("between 1 and 120\n");
                            Console.ForegroundColor = ConsoleColor.White;
                            break;

                        default:
                        return userAge;
                    }
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.Write("TYPE ");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("error\n");
                    Console.Write("Accepted input types are ");
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.Write("numbers (eg. 123) ");
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("between 1 and 120\n");
                    continue;  
                }
            }
        }

When I look at it I feel like all paths should EVENTUALLY lead to:

default:
   return userAge;

If I need to provide the full source code please let me know and I will add it, did not want to make it to messy in case all I needed was the example.

EDIT: I really liked the solution given by @oerkelens but I am struggling to make the userAge variable behave properly. Below Using:(return userAge; inside if statement):

public static int CheckAge()
        {
            int userAge;
            bool inputIsValid = false;
            while (!inputIsValid)
            {
                Console.Write("Enter your age: ");
                string stringAge = Console.ReadLine();

                if (!int.TryParse(stringAge, out userAge))
                {
                    WriteNumericalError();
                    continue;
                }

                if (userAge < 1 || userAge > 120)
                {
                    WriteRangeError();
                    continue;
                }

                inputIsValid = true;
                return userAge;
            }
        }

Gives me the good old: 'Program.CheckAge()': not all code paths return a value

Below Using:(return userAge; outside if statement):

public static int CheckAge()
        {
            int userAge;
            bool inputIsValid = false;
            while (!inputIsValid)
            {
                Console.Write("Enter your age: ");
                string stringAge = Console.ReadLine();

                if (!int.TryParse(stringAge, out userAge))
                {
                    WriteNumericalError();
                    continue;
                }

                if (userAge < 1 || userAge > 120)
                {
                    WriteRangeError();
                    continue;
                }

                inputIsValid = true;
            }
            return userAge;
        }

Solved the 'Program.CheckAge()': not all code paths return a value but introduces: Use of unassigned local variable 'userAge'

FINAL SOLUTION

public static int CheckAge()
        {
            int userAge = 0;
            bool validInput = false;
            while (!validInput)
            {
                Console.Write("Enter your age: ");
                string stringAge = Console.ReadLine();

                if (!int.TryParse(stringAge, out userAge))
                {
                    WriteNumericalError();
                    continue;
                }

                if (userAge < 1 || userAge > 120)
                {
                    WriteRangeError();
                    continue;
                }
                validInput = true;
            }
            return userAge;
        }


        private static void WriteNumericalError()
        {
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write("TYPE ");
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("error\n");
            Console.Write("Accepted input types are numbers ");
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write("(eg. 1 2 3 4 5 6 7 8 9 0)\n");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Press [Enter] to try again");
            Console.ReadLine();
        }

        private static void WriteRangeError()
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("RANGE ");
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("error\n");
            Console.Write("Your entered number does not fall within the accepted range ");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.Write("1 to 5 for film choice - 1 to 120 for age input\n");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("Press [Enter] to try again");
            Console.ReadLine();
        }

First, you're using an obscured infinite loop. Even as while (true) , this seems like a code smell.
Secondly, your flag has a negative meaning. That drives people mad. inValidInput == false means the input is valid!
Third, it's hard to see what you want to accomplish with your code.

Below is an example addressing these things. There are still other possible improvements, but it's a start.

public static int CheckAge()
{
    int userAge = 0; 
    bool inputIsValid = false;
    while (!inputIsValid)
    {
       Console.Write("Enter your age: ");
       string stringAge = Console.ReadLine();

       if (!int.TryParse(stringAge, out userAge))
       {
           WriteNumericalError();
           Continue;
       }
       
       if (userAge < 1 || userAge > 120) 
       {
           WriteRangeError();
           Continue;
       }

       inputIsValid = true;
   }
   return userAge;
}

private void WriteNumericalError()
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.Write("RANGE ");
    Console.ForegroundColor = ConsoleColor.White;
    Console.Write("error\n");
    Console.Write("Accepted range are numbers (eg. 123) ");
    Console.ForegroundColor = ConsoleColor.Red;
    Console.Write("between 1 and 120\n");
    Console.ForegroundColor = ConsoleColor.White;
}
private void WriteRangeError()
{
    Console.ForegroundColor = ConsoleColor.Magenta;
    Console.Write("TYPE ");
    Console.ForegroundColor = ConsoleColor.White;
    Console.Write("error\n");
    Console.Write("Accepted input types are ");
    Console.ForegroundColor = ConsoleColor.Magenta;
    Console.Write("numbers (eg. 123) ");
    Console.ForegroundColor = ConsoleColor.White;
    Console.Write("between 1 and 120\n");
}

In a switch statement the default is only hit if no break point is hit before. In your code, if your first case is met it won't return anything if (n < 1 || n > 120) evaluates to true .

Typically you use break to exit the switch statement and ensure only one case is triggered but in your case you want the case to trigger and the default trigger so you should remove the break .

However, I'd suggest that based on what you currently have a switch statement is less efficient and unnecessarily complicated for what you're doing.

You might try something like this:

public static int CheckAge()
{
    int userAge;

    //while (true) is required to indicate infinite loop and clear the code paths error
    while (true)
    {
        Console.Write("Enter your age: ");
        string stringAge = Console.ReadLine();

        if (int.TryParse(stringAge, out userAge))
        {
            if (userAge < 1 || userAge > 120)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("RANGE ");
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("error\n");
                Console.Write("Accepted range are numbers (eg. 123) ");
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Write("between 1 and 120\n");
                Console.ForegroundColor = ConsoleColor.White;
            }
            else
            {
                return userAge;
            }
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write("TYPE ");
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("error\n");
            Console.Write("Accepted input types are ");
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write("numbers (eg. 123) ");
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("between 1 and 120\n");
        }
    }
}

When I ran your code, the compiler yelled at me saying "not all code paths return a value". I made the two changes commented below and it worked fine for me at that point.

public static int CheckAge()
{
    int userAge = 0; //I added =0 to appease the compiler warnings
    bool inValidInput = true;
    while (inValidInput)
    {
         //your existing code   
    }
    return userAge;  //added this to appease the compiler
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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