Back to Blog
C#

C# Multiple Conditions in If Statement: Combining and Simplifying

c# multiple conditions in if statement: Learn how to combine multiple conditions in C# if statements using &&, ||, parentheses, and pattern matching, with practical ex...

C#if statementslogical operatorsshort-circuitingpattern matchingcode readability
Illustration of combining multiple conditions in a C# if statement with logical operators and parentheses.

When you need to evaluate more than one condition before executing a block, C# provides logical operators to combine them. The most common are && (logical AND) and || (logical OR). This article covers how to use c# multiple conditions in if statement effectively, including operator precedence, short-circuit behavior, and readability improvements.

Combining Conditions with Logical Operators

The simplest way to check multiple conditions is to chain them with && or ||. The && operator returns true only when both operands are true; || returns true when at least one operand is true. For example:

int age = 25; bool hasLicense = true; if (age >= 18 && hasLicense) { Console.WriteLine("You can drive."); }

Here, the if block runs only when both age >= 18 and hasLicense are true. If you need to allow either condition, use ||:

bool isAdmin = false; bool isOwner = true; if (isAdmin || isOwner) { Console.WriteLine("You have access."); }

You can combine more than two conditions, and you can mix && and || in a single expression. When mixing, you must be aware of how C# groups the operators.

Operator Precedence and Parentheses

C# follows standard precedence rules: ! (logical NOT) has the highest priority, then &&, then ||. This means a || b && c is evaluated as a || (b && c), not as (a || b) && c. Consider this example:

bool a = true; bool b = false; bool c = false; if (a || b && c) { Console.WriteLine("This prints because a is true."); }

Even though b && c is false, a is true, so the whole expression is true. If you intended (a || b) && c, you must use parentheses:

if ((a || b) && c) { Console.WriteLine("This does not print because c is false."); }

Parentheses are not just for correctness—they improve readability. When you combine three or more conditions, explicit parentheses make the intent clear to other developers who may not remember precedence rules.

Short-Circuit Evaluation and Side Effects

Both && and || short-circuit. In a && b, if a is false, b is not evaluated. In a || b, if a is true, b is not evaluated. This behavior is useful for avoiding errors and unnecessary work.

A common pattern is to check for null before accessing a member:

string? name = GetName(); if (name != null && name.Length > 3) { Console.WriteLine($"Name {name} is longer than 3 characters."); }

If name is null, the second condition name.Length > 3 never runs, preventing a NullReferenceException. The short-circuit also means that a method call on the right side is skipped when the left side already determines the result. This can save expensive operations, but it also means you should not rely on the right side being evaluated for side effects.

For example, if you write if (isValid && LogAndReturn()), the LogAndReturn method runs only when isValid is true. If you need the logging to happen regardless, place it outside the condition.

Improving Readability for Complex Conditions

Long chains of && and || become hard to read. When a condition spans multiple lines or mixes several checks, extract the logic into a well-named method or property. Compare these two versions:

if (user != null && user.IsActive && user.Role == "Admin" && user.LastLogin > DateTime.UtcNow.AddDays(-30)) { // ... }

That is dense. A clearer version:

if (IsEligibleAdmin(user)) { // ... } private static bool IsEligibleAdmin(User? user) { return user != null && user.IsActive && user.Role == "Admin" && user.LastLogin > DateTime.UtcNow.AddDays(-30); }

Now the condition is self-documenting and can be unit-tested independently. For one-off checks that don't warrant a method, you can assign the result to a local variable:

bool hasRecentLogin = user.LastLogin > DateTime.UtcNow.AddDays(-30); bool isActiveAdmin = user.IsActive && user.Role == "Admin"; if (hasRecentLogin && isActiveAdmin) { // ... }

This keeps the if line short and gives each part a name.

Using Pattern Matching for Multiple Conditions

C# 9 introduced extended property patterns and relational patterns that can replace some if condition chains. For example, you can check a numeric range directly:

int score = 85; if (score is >= 80 and <= 90) { Console.WriteLine("Good score."); }

This is equivalent to score >= 80 && score <= 90. Pattern matching also works with or:

if (score is < 50 or > 100) { Console.WriteLine("Invalid score."); }

For object properties, you can combine patterns:

if (user is { IsActive: true, Role: "Admin" }) { // ... }

This checks that user is not null and both properties match. Pattern matching can be more concise than a long && chain, but it is not always clearer, especially when you need to compare values against variables. Use it when the pattern reads naturally.

Handling Nullable Booleans and Edge Cases

A bool? can be true, false, or null. You cannot use && or || directly on bool? because those operators are not defined for nullable value types. Instead, you must check HasValue first or use the null-coalescing operator:

bool? isEnabled = GetFlag(); if (isEnabled == true) { // Runs only when isEnabled is true } if (isEnabled ?? false) { // Same as above, but treats null as false }

The == true comparison works because bool? has lifted equality. The ?? false pattern is common when you want a default for null. Avoid writing if (isEnabled && ...) because that will not compile. Instead, convert to a non-nullable bool first:

if (isEnabled == true && user.IsActive) { // ... }

This works because isEnabled == true returns a plain bool, which can be combined with &&.

When to Refactor a Complex Condition into a Method

Deciding when to extract a condition depends on how often it is used and how complex it is. If the same condition appears in multiple places, a method eliminates duplication. If a condition is long but used only once, a local variable or a method still improves readability.

A good rule: if you need to scroll horizontally or add a comment to explain the condition, refactor it. The method name should describe the business rule, not the implementation details. For example, IsEligibleForDiscount is better than CheckAgeAndMembership. This makes the if statement read like a sentence and keeps the logic in one place.

Pattern matching and logical operators are both valid tools. Choose the one that best expresses the intent. For simple combinations, && and || are straightforward. For property checks with null safety, pattern matching can be more compact. For conditions that are reused, a method is the maintainable choice.

c# multiple conditions in if statement: Practical Usage and | RYUSLOG DEV