Show / Hide Table of Contents

Pattern Matching

Metaprogramming model support pattern matching statement with the same capabilities as in C# including Recursive Pattern Matching. This statement can be constructed using Match static method from CodeGenerator class.

Supported types of patterns:

  1. Conditional matching
  2. Typed-based matching where you can specify the expected type
  3. Typed-based conditional matching where you can specify the expected type and condition to be applied to the value of this type
  4. Structural matching where you can specify expected values of the properties or fields

Example of structural pattern matching:

using DotNext.Linq.Expressions;
using static DotNext.Metaprogramming.CodeGenerator;

var newState = Lambda<Func<(DoorState, Action, bool), DoorState>>(fun => 
{
    Match(fun[0])
        .Case((DoorState.Closed, Action.Open), DoorState.Opened.Const())
        .Case((DoorState.Opened, Action.Close), DoorState.Closed.Const())
        .Case((DoorState.Closed, Action.Lock, true), DoorState.Locked.Const())
        .Case((DoorState.Locked, Action.Unlock, true), DoorState.Closed.Const())
        .Default(state => state)
        .OfType<DoorState>()
    .End();
}).Compile();

//equivalent generated code is
Func<(DoorState, Action, bool), DoorState> newState = state =>
{
    switch(state) 
    {
        case (DoorState.Closed, Action.Open, _): return DoorState.Opened;
        case (DoorState.Opened, Action.Close, _): return DoorState.Closed;
        case (DoorState.Closed, Action.Lock, true): return DoorState.Locked;
        case (DoorState.Locked, Action.Unlock, true): return DoorState.Closed;
        case (var state, _, _): return state;
    }
}

Structural pattern can be defined using any type including anonymous type. The following example demonstrates various supported patterns:

using DotNext.Linq.Expressions;
using static DotNext.Metaprogramming.CodeGenerator;

struct Point
{
    internal long X, Y;
}

var lambda = Lambda<Func<Point, string>>(fun =>
{
    Match(fun[0])
        .Case("X", 0L.Const(), value => "X is zero".Const())
        .Case(new { X = long.MaxValue, Y = long.MaxValue }, "MaxValue".Const())
        .Case("X", long.MinValue.Const(), "Y", long.MinValue.Const(), (x, y) => "MinValue".Const())
        .Default("Unknown".Const())
        .OfType<string>()
    .End();
}).Compile();

//equivalent generated code is

new Func<Point, string>(point => 
{
    switch(point)
    {
        case {X: 0L}: return "X is zero";
        case {X: long.MaxValue, Y: long.MaxValue}: return "MaxValue";
        case {X: long.MinValue, Y: long.MinValue}: return "MinValue";
        default: return "Unknown";
    }
});
  • Improve this Doc
☀
☾
Back to top Generated by DocFX