๐ŸŽ“ A1Learner
๐Ÿ”
0 of 28 lessons completed

C# Deconstruction Patterns

A deconstruction pattern tests the parts that a value deconstructs into. It can also test properties nested inside other properties in the same match.

Positional patterns on a record

The Point record deconstructs into X and then Y. The second test captures the second part in a variable.

using System;

class Program
{
    static void Main(string[] args)
    {
        Point point = new Point(0, 0);
        Console.WriteLine(point is (0, 0));
        if (point is (0, var y))
        {
            Console.WriteLine(y);
        }
    }
}

record Point(int X, int Y);

A switch over a tuple

Each arm holds a pattern for both elements of the tuple. The first arm needs a true first element and a score of at least 80.

using System;

class Program
{
    static string Result(bool present, int score)
    {
        return (present, score) switch
        {
            (true, >= 80) => "Pass",
            (true, _) => "Try again",
            _ => "Absent"
        };
    }

    static void Main(string[] args)
    {
        Console.WriteLine(Result(true, 85));
    }
}

Nested property patterns

The outer pattern tests the Reading property of the sensor. The inner pattern tests the Value inside that reading.

using System;

class Program
{
    static void Main(string[] args)
    {
        Sensor sensor = new Sensor();
        sensor.Reading = new Reading();
        sensor.Reading.Value = 150;
        if (sensor is { Reading: { Value: > 100 } })
        {
            Console.WriteLine("High");
        }
        else
        {
            Console.WriteLine("Low");
        }
    }
}

class Sensor
{
    public Reading Reading { get; set; }
}

class Reading
{
    public int Value { get; set; }
}

Example

using System;

class Program
{
    static void Main(string[] args)
    {
        Order order = new Order("Pen", 12) { Priority = true };
        string label = order switch
        {
            ("Pen", >= 10) { Priority: true } => "Bulk priority",
            ("Pen", _) { Priority: true } => "Priority",
            _ => "Standard"
        };
        Console.WriteLine(label);
    }
}

record Order(string Item, int Count)
{
    public bool Priority { get; init; }
}

Key points

  • A record deconstructs into its constructor parameters in order.
  • A positional pattern lists the expected parts inside parentheses.
  • A variable inside the pattern captures that part for later use.
  • A tuple can be matched as a whole, with a pattern for each element.
  • A property pattern can nest, so one test reaches through an object graph.
  • A nested test fails as a whole when any part fails to match.

In this example, an Order record holds an item name and a count. The matching arm uses a positional pattern for both parts. The same arm also tests the Priority property. The bulk priority label prints.

Note

A type needs a Deconstruct method or a record shape before a positional pattern can split it.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does the pattern in `new Point(0, 0) is (0, 0)` test?