Conditions
By the end of this lesson
Make a program choose between paths, and keep the conditions readable as they multiply.
Up to now every program has run straight through, doing the same thing every time. A condition lets it choose.
This is the point at which a program stops being a calculator and starts being able to respond.
decimal balance = 42.00m;
if (balance < 0)
{
Console.WriteLine("Account is overdrawn.");
}
else
{
Console.WriteLine("Account is in credit.");
}- The expression in brackets must produce true or false.
- If it is true, the first block runs. Otherwise the else block runs. Exactly one of them happens.
More than two outcomes
int score = 74;
if (score >= 90)
{
Console.WriteLine("Excellent");
}
else if (score >= 70)
{
Console.WriteLine("Good");
}
else if (score >= 50)
{
Console.WriteLine("Pass");
}
else
{
Console.WriteLine("Needs work");
}- Conditions are tested top to bottom, and the first true one wins. Nothing below it is evaluated.
- That is why the order matters: if the >= 50 test came first, a score of 74 would match it and print "Pass".
Keeping complex conditions readable
Conditions tend to grow. A check that starts as one comparison becomes four, and the line turns into something nobody wants to read.
The fix is to name the parts.
if (age >= 18 && hasVerifiedEmail && !isSuspended && country == "IN")
{
// proceed
}bool isAdult = age >= 18;
bool isVerified = hasVerifiedEmail && !isSuspended;
bool isSupportedRegion = country == "IN";
if (isAdult && isVerified && isSupportedRegion)
{
// proceed
}- The logic is unchanged. What changed is that the condition now reads as a sentence, and each part can be understood on its own.
- This also makes the code easier to debug, because you can print any one of the named values to see which part failed.
Summary
- A condition evaluates to true or false and selects which block runs
- In a chain, only the first matching branch executes, so order defines behaviour
- Name the parts of a complex condition so it reads as intent rather than mechanics
- Test boundary values — that is where off-by-one mistakes live
Practice
Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.
Try it yourself
Try it yourself
Write a program that classifies a delivery by weight: under 1kg is "Letter", 1kg to under 10kg is "Parcel", 10kg and above is "Freight".
Test it with 0.5, 1, 9.99, 10 and 25 to confirm the boundaries behave as you intended.
Show solution
Order the tests from smallest upward, or from largest downward — either works, as long as you are consistent. The boundary values are where mistakes hide, which is why they are worth testing explicitly.
decimal weightKg = 9.99m;
string category;
if (weightKg < 1m)
{
category = "Letter";
}
else if (weightKg < 10m)
{
category = "Parcel";
}
else
{
category = "Freight";
}
Console.WriteLine($"{weightKg}kg -> {category}");Think about it
Think about it
In the grading example, what happens to a score of 200? What about -10? Are those results acceptable, and if not, where would you add a check?
Show solution
200 prints "Excellent" and -10 prints "Needs work". Both are arguably wrong, because neither is a valid score.
The real issue is that the code answers a question it was not asked: it classifies rather than validating. A check for out-of-range values belongs before the classification, so invalid input is rejected instead of quietly categorised.
Knowledge check
Nothing is recorded and there is no score. The explanation appears either way.
Saved in this browser only.