PYnative

Python Programming

  • Learn Python ▼
    • Python Tutorials
    • Python Basics
    • Python Interview Q&As
  • Exercises ▼
    • Python Exercises
    • C++ Exercises
    • C Programming Exercises
    • Java Exercises
    • C# Exercises
  • Quizzes
  • Code Editor ▼
    • Online Python Code Editor
    • Online C Compiler
    • Online C++ Compiler
    • Online Java Compiler
    • Online C# Compiler
Home » C# Exercises » C# Pattern Matching Exercises: 20 Coding Problems with Solutions

C# Pattern Matching Exercises: 20 Coding Problems with Solutions

Updated on: July 15, 2026 | Leave a Comment

Modern C# has evolved far beyond basic if and switch statements, and pattern matching is one of its most expressive additions.

This collection of 20 C# pattern matching exercises covers switch expressions, type patterns, property patterns, and relational patterns, giving you concise, readable ways to branch on the shape and content of your data.

Each exercise includes a Practice Problem, Purpose, Hint, and a full Solution with Explanation, so you understand how to apply modern C# syntax in real scenarios.

Also, See: C# Exercises with  22 topic-wise sets and 620+ practice questions.

What You’ll Practice

  • Switch Expressions: Concise, expression-based branching.
  • Type Patterns: Matching and casting based on runtime type.
  • Property Patterns: Matching on an object’s property values.
  • Relational & Logical Patterns: Combining conditions with and, or, and not.
+ Table Of Contents (19 Exercises)

Table of contents

  • Exercise 1: The Status Converter
  • Exercise 2: Boolean Simplifier
  • Exercise 3: Day Classifier
  • Exercise 4: Safe Downcasting
  • Exercise 5: Universal Summer
  • Exercise 6: Collection Detector
  • Exercise 7: E-Commerce Discount
  • Exercise 8: Nested Address Lookup
  • Exercise 9: UI Element State
  • Exercise 10: Quadrant Finder
  • Exercise 11: Login Validator
  • Exercise 12: Traffic Light Simulator
  • Exercise 13: Age Categorizer
  • Exercise 14: Valid Temperature Check
  • Exercise 15: Null and Empty Filter
  • Exercise 16: Array Start Checker
  • Exercise 17: CSV Parser Helper
  • Exercise 18: Slice & Dice
  • Exercise 19: Matrix Game Matrix

Exercise 1: The Status Converter

Practice Problem: Write a method that takes an integer HTTP status code (e.g., 200, 404, 500) and returns a friendly string message using a basic switch expression.

Purpose: This exercise helps you practice writing a basic switch expression as a concise alternative to a switch statement, useful for simple value-to-value mappings like status codes.

Given Input: statusCode = 404

Expected Output: Not Found

▼ Hint
  • Use a switch expression with the form code switch { ... }.
  • Match specific literal values like 200, 404, and 500 as individual case arms.
  • Use _ as the discard pattern to handle any status code not explicitly listed.
  • Return the whole switch expression directly from the method.
▼ Solution & Explanation
using System;

class Program
{
    static string GetStatusMessage(int statusCode) => statusCode switch
    {
        200 => "OK",
        404 => "Not Found",
        500 => "Internal Server Error",
        _ => "Unknown Status Code"
    };

    static void Main()
    {
        Console.WriteLine(GetStatusMessage(404));
    }
}Code language: C# (cs)

Explanation:

  • statusCode switch { ... }: A switch expression evaluates directly to a value, unlike a switch statement which executes a block of code.
  • 200 => "OK": Each arm matches a literal value and produces the corresponding string.
  • _ => "Unknown Status Code": The discard pattern acts as a default case, catching any status code not explicitly listed.
  • Expression-bodied method: The switch expression is returned directly using =>, keeping the method compact.

Exercise 2: Boolean Simplifier

Practice Problem: Create a switch expression that accepts a nullable boolean (bool?) and returns “Yes” for true, “No” for false, and “Maybe” for null.

Purpose: This exercise helps you practice matching against true, false, and null within the same switch expression, showing how nullable value types participate in pattern matching.

Given Input: value = null

Expected Output: Maybe

▼ Hint
  • The parameter type must be bool? so it can hold null in addition to true or false.
  • Match true and false as separate literal patterns.
  • Match null explicitly as its own pattern.
  • Since these three patterns cover every possible value of bool?, no discard arm is required.
▼ Solution & Explanation
using System;

class Program
{
    static string Simplify(bool? value) => value switch
    {
        true => "Yes",
        false => "No",
        null => "Maybe"
    };

    static void Main()
    {
        Console.WriteLine(Simplify(null));
    }
}Code language: C# (cs)

Explanation:

  • bool? value: A nullable bool parameter, allowing three possible states: true, false, and null.
  • true => "Yes" and false => "No": Match the two literal boolean values directly.
  • null => "Maybe": Matches the absence of a value as its own distinct pattern.
  • No discard needed: Because true, false, and null cover every possible value of bool?, the compiler doesn’t require a fallback _ arm.

Exercise 3: Day Classifier

Practice Problem: Given an enum DayOfWeek, use pattern matching to return “Weekend” for Saturday and Sunday, and “Weekday” for everything else.

Purpose: This exercise helps you practice combining multiple case labels with the or pattern to group related enum values into a single result.

Given Input: day = DayOfWeek.Saturday

Expected Output: Weekend

▼ Hint
  • Use the built-in System.DayOfWeek enum as the parameter type.
  • Combine Saturday and Sunday using the or pattern in a single case.
  • Use _ to catch all remaining weekday values in one fallback arm.
  • Return the whole expression using a switch expression on the enum parameter.
▼ Solution & Explanation
using System;

class Program
{
    static string ClassifyDay(DayOfWeek day) => day switch
    {
        DayOfWeek.Saturday or DayOfWeek.Sunday => "Weekend",
        _ => "Weekday"
    };

    static void Main()
    {
        Console.WriteLine(ClassifyDay(DayOfWeek.Saturday));
    }
}Code language: C# (cs)

Explanation:

  • DayOfWeek.Saturday or DayOfWeek.Sunday: Combines two enum values into a single case using the or pattern, avoiding two separate arms with the same result.
  • _ => "Weekday": Matches every other day of the week with a single fallback arm.
  • day switch { ... }: The switch expression evaluates the enum value once and returns the matching string.
  • System.DayOfWeek: Reused directly from the framework instead of declaring a custom enum.

Exercise 4: Safe Downcasting

Practice Problem: Write a method DescribeShape(object shape) that returns “It’s a circle with radius R” if it’s a Circle object, “It’s a rectangle” if it’s a Rectangle, and “Unknown shape” otherwise.

Purpose: This exercise helps you practice using type patterns to safely check and cast an object in one step, avoiding a manual is check followed by a separate explicit cast.

Given Input: shape = new Circle(5)

Expected Output: It's a circle with radius 5

▼ Hint
  • Define simple Circle and Rectangle classes with the relevant properties, such as Radius on Circle.
  • Use a type pattern like Circle c inside a switch expression to both check and capture the object as that type.
  • Reference the captured variable’s properties directly inside that same arm.
  • Add a final _ arm to handle any object that isn’t a recognized shape.
▼ Solution & Explanation
using System;

class Circle
{
    public double Radius { get; set; }
    public Circle(double radius) { Radius = radius; }
}

class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }
}

class Program
{
    static string DescribeShape(object shape) => shape switch
    {
        Circle c => "It's a circle with radius " + c.Radius,
        Rectangle => "It's a rectangle",
        _ => "Unknown shape"
    };

    static void Main()
    {
        Console.WriteLine(DescribeShape(new Circle(5)));
    }
}Code language: C# (cs)

Explanation:

  • Circle c => ...: A type pattern that checks whether shape is a Circle and, if so, captures it in the variable c so its Radius can be used directly.
  • Rectangle => "It's a rectangle": A type pattern that only needs to confirm the type, so no variable name is required here.
  • _ => "Unknown shape": Handles any object that isn’t a Circle or a Rectangle, since type patterns never match null either.
  • Single expression: Replaces what would otherwise be an is check followed by a manual cast, combining both steps into one pattern.

Exercise 5: Universal Summer

Practice Problem: Create a function that accepts an object. If it’s an int, return the int. If it’s a string that can be parsed into an int, parse and return it. Otherwise, return 0.

Purpose: This exercise helps you practice combining type patterns with additional conditions to handle multiple possible input types safely, common when working with loosely typed data.

Given Input: Three calls: ToInt(42), ToInt("100"), ToInt("abc")

Expected Output:

42
100
0
▼ Hint
  • Match an int pattern first, to handle the case where the value is already a number.
  • Match a string pattern, capturing it in a variable so it can be passed to int.TryParse.
  • Use a when clause with TryParse inside that arm to confirm the string can be converted before returning the parsed value.
  • Add a final _ arm returning 0 for anything else, including strings that can’t be parsed.
▼ Solution & Explanation
using System;

class Program
{
    static int ToInt(object value) => value switch
    {
        int i => i,
        string s when int.TryParse(s, out int result) => result,
        _ => 0
    };

    static void Main()
    {
        Console.WriteLine(ToInt(42));
        Console.WriteLine(ToInt("100"));
        Console.WriteLine(ToInt("abc"));
    }
}Code language: C# (cs)

Explanation:

  • int i => i: Matches when the value is already an int, returning it directly without any conversion.
  • string s when int.TryParse(s, out int result) => result: Matches a string only if it can be successfully parsed, using a when clause to add that extra condition to the pattern.
  • Failed parse: If TryParse fails, as with "abc", the pattern doesn’t match, so the switch expression moves on to the next arm instead of throwing an exception.
  • _ => 0: The fallback for any value that is neither an int nor a parseable string.

Exercise 6: Collection Detector

Practice Problem: Write a method that takes an object and returns a string identifying if it is a List<int>, an int[] array, or “Other collection type”.

Purpose: This exercise helps you practice using type patterns to distinguish between different concrete collection types passed as a general object parameter.

Given Input: A List<int>, an int[], and a Dictionary<string, int>, passed one at a time.

Expected Output:

List<int>
int array
Other collection type
▼ Hint
  • Match List<int> using a type pattern as the first case.
  • Match int[] using a type pattern as the second case.
  • Keep the arms ordered from specific to general, since a switch expression checks patterns from top to bottom.
  • Use _ for anything that doesn’t match either specific collection type.
▼ Solution & Explanation
using System;
using System.Collections.Generic;

class Program
{
    static string DescribeCollection(object collection) => collection switch
    {
        List<int> => "List<int>",
        int[] => "int array",
        _ => "Other collection type"
    };

    static void Main()
    {
        Console.WriteLine(DescribeCollection(new List<int> { 1, 2, 3 }));
        Console.WriteLine(DescribeCollection(new int[] { 1, 2, 3 }));
        Console.WriteLine(DescribeCollection(new Dictionary<string, int>()));
    }
}Code language: C# (cs)

Explanation:

  • List<int> => "List<int>": Matches only when the object’s runtime type is exactly List<int>, not other generic list types.
  • int[] => "int array": Matches when the object is an integer array specifically.
  • Pattern order: More specific patterns are placed before the general fallback, since a switch expression evaluates its arms in order.
  • _ => "Other collection type": Catches everything else, including other generic collections like Dictionary<string, int>.

Exercise 7: E-Commerce Discount

Practice Problem: Given an Order class with properties TotalPrice (decimal) and IsPremiumCustomer (bool), write a switch expression to calculate discounts: 20% for premium customers with orders over $100, 10% for premium customers under $100, and 0% for everyone else.

Purpose: This exercise helps you practice combining property patterns with additional conditions using when clauses, useful for encoding business rules concisely.

Given Input: Order { TotalPrice = 150, IsPremiumCustomer = true }

Expected Output: Discount = 20%

▼ Hint
  • Use a property pattern like { IsPremiumCustomer: true } combined with a when clause checking TotalPrice.
  • Order the cases from most specific to least specific, since the first matching arm wins.
  • Add a case for premium customers under the $100 threshold with a different discount.
  • Add a final _ arm returning 0% for all non-premium customers.
▼ Solution & Explanation
using System;

class Order
{
    public decimal TotalPrice { get; set; }
    public bool IsPremiumCustomer { get; set; }
}

class Program
{
    static string GetDiscount(Order order) => order switch
    {
        { IsPremiumCustomer: true } when order.TotalPrice > 100 => "Discount = 20%",
        { IsPremiumCustomer: true } => "Discount = 10%",
        _ => "Discount = 0%"
    };

    static void Main()
    {
        Order order = new Order { TotalPrice = 150, IsPremiumCustomer = true };
        Console.WriteLine(GetDiscount(order));
    }
}Code language: C# (cs)

Explanation:

  • { IsPremiumCustomer: true } when order.TotalPrice > 100: A property pattern combined with a when clause, matching only premium customers whose order also exceeds $100.
  • { IsPremiumCustomer: true } => "Discount = 10%": Matches any remaining premium customer that didn’t satisfy the first, more specific arm.
  • Arm order matters: The over-$100 premium case is placed first so it is checked before the general premium case.
  • _ => "Discount = 0%": Covers every non-premium customer, regardless of their total price.

Exercise 8: Nested Address Lookup

Practice Problem: You have a User object containing a Profile object, which contains an Address object with a Country string. Use property patterns to check if the user is from “Canada” in a single line.

Purpose: This exercise helps you practice nested property patterns, which let you reach into related objects several levels deep without writing a chain of null checks.

Given Input: A User whose Profile.Address.Country is "Canada".

Expected Output: User is from Canada

▼ Hint
  • Define User, Profile, and Address classes, each holding a reference to the next.
  • Use a nested property pattern like { Profile: { Address: { Country: "Canada" } } }.
  • This single pattern replaces what would otherwise require three separate null checks.
  • Return a different message for users whose nested Country doesn’t match.
▼ Solution & Explanation
using System;

class Address
{
    public string Country { get; set; }
}

class Profile
{
    public Address Address { get; set; }
}

class User
{
    public Profile Profile { get; set; }
}

class Program
{
    static string CheckCountry(User user) => user switch
    {
        { Profile: { Address: { Country: "Canada" } } } => "User is from Canada",
        _ => "User is not from Canada"
    };

    static void Main()
    {
        User user = new User
        {
            Profile = new Profile
            {
                Address = new Address { Country = "Canada" }
            }
        };

        Console.WriteLine(CheckCountry(user));
    }
}Code language: C# (cs)

Explanation:

  • { Profile: { Address: { Country: "Canada" } } }: A nested property pattern that drills into Profile, then Address, then Country, all in a single expression.
  • Implicit null safety: If Profile or Address were null anywhere along the chain, the pattern simply fails to match instead of throwing a NullReferenceException.
  • Compared to manual checks: This replaces what would otherwise require checking user.Profile != null, then user.Profile.Address != null, before finally comparing Country.
  • _ => "User is not from Canada": Handles every case where the nested pattern doesn’t match, including a null Profile or Address.

Exercise 9: UI Element State

Practice Problem: Create a switch expression that evaluates a Button control based on its properties: IsEnabled = false returns “Disabled”, IsHovered = true returns “Highlighted”, and IsPressed = true returns “Clicked”.

Purpose: This exercise helps you practice ordering multiple property patterns so the most important state takes priority over the others.

Given Input: Button { IsEnabled = true, IsHovered = false, IsPressed = true }

Expected Output: Clicked

▼ Hint
  • Define a Button class with IsEnabled, IsHovered, and IsPressed boolean properties.
  • Check IsEnabled: false first, since a disabled button should report its state regardless of hover or press.
  • Check IsHovered: true next, followed by IsPressed: true, matching the priority order given in the problem.
  • Add a final case or discard for the default, unhighlighted and unpressed state.
▼ Solution & Explanation
using System;

class Button
{
    public bool IsEnabled { get; set; }
    public bool IsHovered { get; set; }
    public bool IsPressed { get; set; }
}

class Program
{
    static string GetState(Button button) => button switch
    {
        { IsEnabled: false } => "Disabled",
        { IsHovered: true } => "Highlighted",
        { IsPressed: true } => "Clicked",
        _ => "Normal"
    };

    static void Main()
    {
        Button button = new Button { IsEnabled = true, IsHovered = false, IsPressed = true };
        Console.WriteLine(GetState(button));
    }
}Code language: C# (cs)

Explanation:

  • { IsEnabled: false } => "Disabled": Checked first, since a disabled button should report its state regardless of hover or press flags.
  • { IsHovered: true } => "Highlighted": Checked next, taking priority over the pressed state in this ordering.
  • { IsPressed: true } => "Clicked": Only reached if the button is enabled and not currently hovered.
  • _ => "Normal": The fallback for a button that is enabled, not hovered, and not pressed.

Exercise 10: Quadrant Finder

Practice Problem: Create a Point record with int X and int Y. Use a positional pattern to determine which quadrant the point lies in (e.g., return “Quadrant 1” if both X and Y are positive).

Purpose: This exercise helps you practice positional patterns with records, which let you deconstruct a record’s properties directly inside a switch expression.

Given Input: Point(3, 4)

Expected Output: Quadrant 1

▼ Hint
  • Declare Point as a record with positional parameters X and Y.
  • Use a positional pattern like (> 0, > 0) to match both coordinates being positive at once.
  • Add separate arms for the other three quadrant combinations.
  • Include a discard arm for points that lie on an axis, where X or Y equals zero.
▼ Solution & Explanation
using System;

record Point(int X, int Y);

class Program
{
    static string GetQuadrant(Point point) => point switch
    {
        (> 0, > 0) => "Quadrant 1",
        (< 0, > 0) => "Quadrant 2",
        (< 0, < 0) => "Quadrant 3",
        (> 0, < 0) => "Quadrant 4",
        _ => "On an axis"
    };

    static void Main()
    {
        Point point = new Point(3, 4);
        Console.WriteLine(GetQuadrant(point));
    }
}Code language: C# (cs)

Explanation:

  • record Point(int X, int Y): A record with positional parameters, which automatically supports deconstruction into X and Y for pattern matching.
  • (> 0, > 0) => "Quadrant 1": A positional pattern that deconstructs the point and applies a relational pattern to each coordinate in one step.
  • Relational patterns: Patterns like > 0 and < 0 check numeric ranges directly inside the pattern instead of requiring separate if conditions.
  • _ => "On an axis": Handles any point where X or Y is exactly zero, since none of the four quadrant patterns would match.

Exercise 11: Login Validator

Practice Problem: Given a tuple (string username, string password), use pattern matching to return true if the credentials match a specific admin account, and false otherwise.

Purpose: This exercise helps you practice matching against tuple patterns, letting you check multiple values together in a single switch expression instead of chaining separate comparisons.

Given Input: Two login attempts: ("admin", "P@ssw0rd") and ("admin", "wrongpass").

Expected Output:

True
False
▼ Hint
  • Declare the parameter type as a tuple, (string username, string password).
  • Use a tuple pattern like ("admin", "P@ssw0rd") to match both values at the same time.
  • Add a discard pattern _ as the final arm to return false for any other combination.
  • Call the method twice with different credentials to see both outcomes.
▼ Solution & Explanation
using System;

class Program
{
    static bool ValidateLogin((string username, string password) credentials) => credentials switch
    {
        ("admin", "P@ssw0rd") => true,
        _ => false
    };

    static void Main()
    {
        Console.WriteLine(ValidateLogin(("admin", "P@ssw0rd")));
        Console.WriteLine(ValidateLogin(("admin", "wrongpass")));
    }
}Code language: C# (cs)

Explanation:

  • (string username, string password) credentials: A tuple parameter that groups the username and password into a single value.
  • ("admin", "P@ssw0rd") => true: A tuple pattern that matches only when both elements equal the specified literals at the same time.
  • _ => false: Catches every other combination, including a correct username paired with an incorrect password.
  • Single expression: Replaces what would otherwise require two separate == comparisons joined by &&.

Exercise 12: Traffic Light Simulator

Practice Problem: Given a tuple of (CurrentLight, PedestrianWaiting), return the next state of the traffic light (e.g., if it’s Red and a pedestrian is waiting, keep it Red; if no one is waiting, turn it Green).

Purpose: This exercise helps you practice building a small state machine using tuple patterns, where the combination of two values together determines the result, not either value on its own.

Given Input: (current = Red, pedestrianWaiting = true)

Expected Output: Red

▼ Hint
  • Represent the input as a tuple, (LightState current, bool pedestrianWaiting).
  • Match (Red, true) to keep the light red while a pedestrian is still waiting.
  • Match (Red, false) to allow the light to change to green once no one is waiting.
  • Add the remaining tuple patterns to complete the full state machine for Yellow and Green.
▼ Solution & Explanation
using System;

enum LightState
{
    Red,
    Yellow,
    Green
}

class Program
{
    static LightState GetNextState((LightState current, bool pedestrianWaiting) state) => state switch
    {
        (LightState.Red, true) => LightState.Red,
        (LightState.Red, false) => LightState.Green,
        (LightState.Green, true) => LightState.Yellow,
        (LightState.Green, false) => LightState.Green,
        (LightState.Yellow, _) => LightState.Red
    };

    static void Main()
    {
        LightState next = GetNextState((LightState.Red, true));
        Console.WriteLine(next);
    }
}Code language: C# (cs)

Explanation:

  • (LightState current, bool pedestrianWaiting): A tuple parameter combining the current light and whether a pedestrian is waiting.
  • (LightState.Red, true) => LightState.Red: Matches both elements together, keeping the light red as long as a pedestrian is still waiting.
  • (LightState.Red, false) => LightState.Green: Matches when no pedestrian is waiting, allowing the light to change.
  • (LightState.Yellow, _) => LightState.Red: Uses a discard for the second element since a yellow light always moves to red regardless of pedestrian status.

Exercise 13: Age Categorizer

Practice Problem: Write a switch expression that takes an int age and uses relational patterns to return “Child” (under 13), “Teenager” (13 to 19), “Adult” (20 to 64), and “Senior” (65 or older).

Purpose: This exercise helps you practice relational patterns combined with the and pattern to express inclusive ranges directly inside a switch expression.

Given Input: age = 45

Expected Output: Adult

▼ Hint
  • Use < 13 as a relational pattern for the child case.
  • Combine >= 13 and <= 19 using the and pattern for the teenager range.
  • Combine >= 20 and <= 64 using the and pattern for the adult range.
  • Use >= 65 as the final relational pattern for the senior case.
▼ Solution & Explanation
using System;

class Program
{
    static string CategorizeAge(int age) => age switch
    {
        < 13 => "Child",
        >= 13 and <= 19 => "Teenager",
        >= 20 and <= 64 => "Adult",
        >= 65 => "Senior"
    };

    static void Main()
    {
        Console.WriteLine(CategorizeAge(45));
    }
}Code language: C# (cs)

Explanation:

  • < 13 => "Child": A relational pattern matching any age below 13.
  • >= 13 and <= 19 => "Teenager": Combines two relational patterns with the and pattern to express an inclusive range.
  • >= 20 and <= 64 => "Adult": Applies the same technique to the adult range.
  • >= 65 => "Senior": A single relational pattern covers every remaining age, since it’s the highest range in the sequence.

Exercise 14: Valid Temperature Check

Practice Problem: Write a method that returns true if a temperature double is within a safe operating range: greater than 0.0 and less than or equal to 100.0.

Purpose: This exercise helps you practice combining two relational patterns with and inside a single is expression, an alternative to writing separate comparisons joined by &&.

Given Input: temperature = 37.5

Expected Output: True

▼ Hint
  • Use the is keyword with a pattern rather than a switch expression, since this method only needs a single true or false result.
  • Combine > 0.0 and <= 100.0 using the and pattern inside that single is expression.
  • Return the result of the is expression directly from the method.
  • Test a value outside the range separately to confirm the method returns false.
▼ Solution & Explanation
using System;

class Program
{
    static bool IsValidTemperature(double temperature) => temperature is > 0.0 and <= 100.0;

    static void Main()
    {
        Console.WriteLine(IsValidTemperature(37.5));
    }
}Code language: C# (cs)

Explanation:

  • temperature is > 0.0 and <= 100.0: A single pattern-matching expression combining two relational patterns, equivalent to temperature > 0.0 && temperature <= 100.0.
  • and pattern: Requires the value to satisfy both relational conditions at once rather than either one alone.
  • is expression: Returns a bool directly, making it well suited for a single validation check instead of a full switch expression.
  • Boundary behavior: A temperature of exactly 100.0 still returns true, while 0.0 itself returns false, since the lower bound is exclusive.

Exercise 15: Null and Empty Filter

Practice Problem: Write a pattern that checks if an object is not null and is not an empty string.

Purpose: This exercise helps you practice using the not pattern to express negative conditions clearly, instead of relying on != and manual length checks.

Given Input: Two values: "Hello" and "".

Expected Output:

True
False
▼ Hint
  • Use the not pattern to require that the value is not null.
  • Combine it with another not pattern checking against the empty string constant "".
  • Join both conditions using and so the value must satisfy each one independently.
  • Test both a normal string and an empty string to see the difference in the result.
▼ Solution & Explanation
using System;

class Program
{
    static bool IsValid(object value) => value is not null and not "";

    static void Main()
    {
        Console.WriteLine(IsValid("Hello"));
        Console.WriteLine(IsValid(""));
    }
}Code language: C# (cs)

Explanation:

  • not null: A negated pattern that matches any value except null.
  • not "": A negated constant pattern that matches any value except the specific empty string.
  • and: Requires both negated patterns to hold true, so a null value or an empty string returns false.
  • object value: Because the parameter type is object, the same check works for any value, not just strings, since a non-string value would already satisfy not "".

Exercise 16: Array Start Checker

Practice Problem: Write a method that accepts an int[] and returns true if the array starts with the numbers 1, 2, 3, regardless of what follows.

Purpose: This exercise helps you practice using a list pattern with a trailing slice pattern to check the beginning of a sequence without caring about its remaining length.

Given Input: numbers = [1, 2, 3, 4, 5]

Expected Output: True

▼ Hint
  • Use a list pattern with square brackets to match against the array’s elements directly.
  • Specify the first three elements as literal values: 1, 2, 3.
  • Follow those with the slice pattern .. to allow any number of additional elements afterward.
  • Test with an array that doesn’t start with 1, 2, 3 to confirm it returns false.
▼ Solution & Explanation
using System;

class Program
{
    static bool StartsWithOneTwoThree(int[] numbers) => numbers is [1, 2, 3, ..];

    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        Console.WriteLine(StartsWithOneTwoThree(numbers));
    }
}Code language: C# (cs)

Explanation:

  • numbers is [1, 2, 3, ..]: A list pattern matching an array whose first three elements are exactly 1, 2, and 3.
  • .. (slice pattern): Matches any number of remaining elements, including zero, so the array can be any length as long as it starts correctly.
  • List patterns: Work directly against arrays and other countable, indexable types without needing to call methods like Take or manually index into the array.
  • Short-circuit behavior: If the array has fewer than three elements, the pattern simply fails to match instead of throwing an exception.

Exercise 17: CSV Parser Helper

Practice Problem: Given a string[] representing a split CSV row, match rows that have exactly three elements where the first element is “ID” and the last is “Active”.

Purpose: This exercise helps you practice combining an exact-length list pattern with specific literal values at fixed positions, while leaving the middle element unconstrained.

Given Input: row = ["ID", "42", "Active"]

Expected Output: True

▼ Hint
  • Use a list pattern with exactly three elements inside the square brackets.
  • Match the first element against the literal "ID".
  • Use a discard _ for the middle element, since its value doesn’t matter.
  • Match the last element against the literal "Active".
▼ Solution & Explanation
using System;

class Program
{
    static bool IsActiveIdRow(string[] row) => row is ["ID", _, "Active"];

    static void Main()
    {
        string[] row = { "ID", "42", "Active" };
        Console.WriteLine(IsActiveIdRow(row));
    }
}Code language: C# (cs)

Explanation:

  • row is ["ID", _, "Active"]: A list pattern requiring exactly three elements, since no slice pattern is present.
  • "ID" and "Active": Literal patterns pinning the first and last elements to specific values.
  • _: A discard pattern for the middle element, matching any value without capturing it.
  • Exact length requirement: A row with two elements or four elements would not match this pattern at all, regardless of its content.

Exercise 18: Slice & Dice

Practice Problem: Write a list pattern using the discard (_) and slice (..) operators to check if an array contains at least two elements, where the first element is 0 and the last element is 9.

Purpose: This exercise helps you practice combining the slice pattern with fixed first and last elements to validate the ends of a sequence while ignoring everything in between.

Given Input: numbers = [0, 4, 7, 9]

Expected Output: True

▼ Hint
  • Use a list pattern with the first element matched against 0.
  • Follow it with the slice pattern .. to allow any number of elements in between, including none.
  • Match the last element against 9 as the final element in the pattern.
  • Test with an array of exactly two elements, [0, 9], to confirm the slice pattern can also match zero elements in between.
▼ Solution & Explanation
using System;

class Program
{
    static bool StartsAndEndsCorrectly(int[] numbers) => numbers is [0, .., 9];

    static void Main()
    {
        int[] numbers = { 0, 4, 7, 9 };
        Console.WriteLine(StartsAndEndsCorrectly(numbers));
    }
}Code language: C# (cs)

Explanation:

  • numbers is [0, .., 9]: A list pattern pinning the first element to 0 and the last element to 9, with .. absorbing everything in between.
  • .. in the middle: Matches zero or more elements, so both [0, 9] and [0, 4, 7, 9] satisfy the same pattern.
  • Minimum length: The pattern still requires at least two elements, since the first and last positions cannot overlap.
  • No extra discard needed: The slice pattern already ignores its contents entirely, so a separate _ for the middle section isn’t required.

Exercise 19: Matrix Game Matrix

Practice Problem: Given an array of char arrays representing a Tic-Tac-Toe board, use list patterns to check if the first row has a winning line of ['X', 'X', 'X'].

Purpose: This exercise helps you practice applying a list pattern to one row of a two-dimensional structure, useful for validating game state or grid-based logic.

Given Input: A board whose first row is ['X', 'X', 'X'].

Expected Output: First row is a winning line

▼ Hint
  • Represent the board as a jagged array, char[][], where each inner array is one row.
  • Access the first row with board[0] and apply a list pattern directly to it.
  • Match the row against ['X', 'X', 'X'] to check for a winning line of X’s.
  • Return a different message if the first row doesn’t match that exact pattern.
▼ Solution & Explanation
using System;

class Program
{
    static string CheckFirstRow(char[][] board)
    {
        return board[0] switch
        {
            ['X', 'X', 'X'] => "First row is a winning line",
            _ => "First row is not a winning line"
        };
    }

    static void Main()
    {
        char[][] board =
        {
            new char[] { 'X', 'X', 'X' },
            new char[] { 'O', 'X', 'O' },
            new char[] { 'O', 'O', 'X' }
        };

        Console.WriteLine(CheckFirstRow(board));
    }
}Code language: C# (cs)

Explanation:

  • board[0]: Extracts the first row from the jagged array before the pattern is applied to it.
  • ['X', 'X', 'X']: A list pattern requiring exactly three elements, each matching the literal character 'X'.
  • Switch expression on a single row: Applies the same list pattern technique used for one-dimensional arrays, just to a row extracted from a larger grid.
  • _ => "First row is not a winning line": Handles any row that doesn’t consist of exactly three X’s, including rows with a mix of X, O, or a different length.

Filed Under: C# Exercises

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

TweetF  sharein  shareP  Pin

About Vishal

I’m Vishal Hule, the Founder of PYnative.com. As a Python developer, I enjoy assisting students, developers, and learners. Follow me on Twitter.

Related Tutorial Topics:

C# Exercises

All Coding Exercises:

C Exercises
C++ Exercises
Python Exercises
Java Exercises
C# Exercises

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 25+ questions
  • Each Quiz contains 25 MCQ
Exercises
Quizzes

Leave a Reply Cancel reply

your email address will NOT be published. all comments are moderated according to our comment policy.

Use <pre> tag for posting code. E.g. <pre> Your entire code </pre>

In: C# Exercises
TweetF  sharein  shareP  Pin

  C# Exercises

  • C# Exercise for Beginners
  • C# Loops Exercise
  • C# Array Exercise
  • C# String Exercise
  • C# OOP Exercise
  • C# Structs, Records and Enums Exercise
  • C# Collections Exercise
  • C# List Exercise
  • C# Dictionary Exercise
  • C# LINQ Exercise
  • C# Exception Handling Exercise
  • C# File Handling Exercise
  • C# Date and Time Exercise
  • C# Generics Exercise
  • C# Lambda Expressions Exercise
  • C# Delegates and Events Exercise
  • C# Extension Methods Exercise
  • C# Regex Exercise
  • C# Pattern Matching Exercise
  • C# Iterators and Yield Exercise
  • C# Indexers and Operator Overloading Exercise
  • C# Random Data Generation Exercise

All Coding Exercises

Python Exercises C Exercises C++ Exercises Java Exercises C# Exercises

About PYnative

PYnative.com is for Python lovers. Here, You can get Tutorials, Exercises, and Quizzes to practice and improve your Python skills.

Follow Us

To get New Python Tutorials, Exercises, and Quizzes

  • Twitter
  • Facebook
  • Sitemap

Explore Python

  • Learn Python
  • Python Basics
  • Python Databases
  • Python Exercises
  • Python Quizzes
  • Online Python Code Editor
  • Python Tricks

Coding Exercises

  • C Exercises
  • C++ Exercises
  • Python Exercises
  • Java Exercises
  • C# Exercises

Legal Stuff

  • About Us
  • Contact Us

We use cookies to improve your experience. While using PYnative, you agree to have read and accepted our:

  • Terms Of Use
  • Privacy Policy
  • Cookie Policy

Copyright © 2018–2026 pynative.com