You are very much correct that switch
statements cannot take boolean operators like that: switch
statements are used to build jump tables, and can only use constants to do so. However, you can easily come up with a fairly robust solution to your problem using a Dictionary
and some LINQ.
Since you tagged your question beginner I'll be gentle with the explanation.
The first thing we'll do is make a Dictionary<int, string>
which represents the lowest value associated with each grade.
var gradeMap = new Dictionary<int, string>
{
[0] = "X",
[201] = "A",
[401] = "B",
[801] = "Z",
};
So, this means if the value is >= 801
, then it's Z
, and so on.
Next, we'll simply one-line this entire operation in LINQ:
gradeMap.OrderByDescending(x => x.Key).FirstOrDefault(x => x.Key <= testWeight).Value
What's happening here? LINQ is Language Integrated Query, if you've ever worked with SQL you might recognize the Query bit, essentially, LINQ allows you to build code which looks and act's like a query against an IEnumerable
object (which Dictionary
is).
So if we take this step-by-step, we can start with our dictionary as follows:
0: X
201: A
401: B
801: Z
The gradeMap.OrderByDescending(x => x.Key)
bit will first take the entire gradeMap
dictionary, and order it by the key value in highest-to-lowest order:
801: Z
401: B
201: A
0: X
Next, we do a FirstOrDefault(x => x.Key <= testWeight)
, which will loop through all the elements (in the backwards order we have them) that are in the dictionary, and find the first one that matches our expression (x.Key <= testWeight
). The x.Key
is the reference to the key of the dictionary (our int
values):
801: Z (Skipped)
401: B (Skipped)
201: A (Matched)
So, now we have the 201: A
item from the dictionary, the last part is to get .Value
on it which returns the string
portion of it:
A
And viola, we have our value. :)
We can combine this together and get:
var testWeight = 205;
var grade = gradeMap.OrderByDescending(x => x.Key).FirstOrDefault(x => x.Key <= testWeight).Value;
So, the final thing we have to do is combine it with your original programme:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class Program
{
static int GetIntNumber(int min, int max, string prompt, string inputPrompt)
{
int number;
Console.Write(prompt);
do //loops as long as input is not between min and max
{
while (!int.TryParse(Console.ReadLine(), out number)) //loops as long as the input is not an integer
{
Console.Write("\nYou must enter an integer number!: ");
}
if (number < min || number > max) Console.Write(inputPrompt); //<--| write input prompt if number out of range
} while (number < min || number > max);
return number;
}
static void printGrade(string grade)
{
Console.WriteLine("\nYour potato is grade " + grade);
}
static void Main()
{
do
{
var gradeMap = new Dictionary<int, string>
{
[0] = "X",
[201] = "A",
[401] = "B",
[801] = "Z",
};
int weight = GetIntNumber(0, 1500, "\nEnter the weight of the potato in grams: ", "\nEnter an integer between 0 and 1500: ");
printGrade(gradeMap.OrderByDescending(x => x.Key).FirstOrDefault(x => x.Key <= weight).Value);
Console.WriteLine("\nPress any key to check the grade of another potato.");
} while (Console.ReadKey(true).Key != ConsoleKey.Escape );
Console.Read();
}
}
The next best thing would be to extract the LINQ logic into a new method:
public string GetGrade(int weight)
{
var gradeMap = new Dictionary<int, string>
{
[0] = "X",
[201] = "A",
[401] = "B",
[801] = "Z",
};
return gradeMap.OrderByDescending(x => x.Key).FirstOrDefault(x => x.Key <= weight).Value;
}
Then our Main
method becomes:
static void Main()
{
do
{
int weight = GetIntNumber(0, 1500, "\nEnter the weight of the potato in grams: ", "\nEnter an integer between 0 and 1500: ");
printGrade(GetGrade(weight));
Console.WriteLine("\nPress any key to check the grade of another potato.");
} while (Console.ReadKey(true).Key != ConsoleKey.Escape );
Console.Read();
}
Now if you need to add a new grade, for whatever reason, it's trivial.
Also: if you're not using C#6.0, you will have to replace var gradeMap
with the following:
var gradeMap = new Dictionary<int, string>
{
{0, "X"},
{201, "A"},
{401, "B"},
{801, "Z"}
};
Good work so far, hopefully you continue improving and learn more regarding C# and the paradigms it holds. :)
The answer by t3chb0t is also very good, I recommend reading it thoroughly as well (especially the bit about method overloading).
printGrade( weight < 201 ? "X" : weight < 401 ? "A" : weight < 801 ? "B" : "Z" )
\$\endgroup\$