Functional pattern matching in C# I recently read a really interesting post on adding functional pattern matching to C#. Here's a quick and dirty implementation using delegates and dictionaries. 

Right now, I require that Match return an object of type TReturn. Is there any way I can easily extend my current implementation to be void (i.e. Match is not required to return anything) without significant code duplication? When I first tried this, I ended up essentially copying Match but omitting the second type parameter. 

/// &lt;summary&gt;
/// Represents a switch on TIn. 
/// &lt;/summary&gt;
public class Match&lt;TIn, TReturn&gt;
{
    private Dictionary&lt;Type, Delegate&gt; funcs =
        new Dictionary&lt;Type, Delegate&gt;();

    private Dictionary&lt;TIn, TReturn&gt; values =
        new Dictionary&lt;TIn, TReturn&gt;();

    private TReturn _else;

    /// &lt;summary&gt;
    /// Adds a case, action pair
    /// &lt;/summary&gt;
    public void Case&lt;T&gt;(Func&lt;T, TReturn&gt; func)
        where T : TIn
    {
        funcs[typeof(T)] = func;
    }

    /// &lt;summary&gt;
    /// Adds a case, value pair
    /// &lt;/summary&gt;
    public void Case(TIn x, TReturn value)
    {
        values[x] = value;
    }

    /// &lt;summary&gt;
    /// Adds the default case value
    /// &lt;/summary&gt;
    public void Else(TIn x, TReturn value)
    {
        _else = value;
    }

    /// &lt;summary&gt;
    /// Evaluates the match on a query
    /// Returns an object of type TReturn 
    /// for first successful match
    /// &lt;/summary&gt;
    public TReturn Eval&lt;T&gt;(T query) 
        where T : TIn 
    {
        TReturn value;
        if (values.TryGetValue(query, out value))
            return value;

        Delegate func;
        if (funcs.TryGetValue(query.GetType(), out func))
            return (TReturn)func.DynamicInvoke(query);

        return _else;
    }
}


And here's a simple test. One thing I was wondering: is it inefficient to declare a new Match inside the Calculate method? 

class Program
{
    public static double Calculate(Expression exp)
    {
        var match = new Match&lt;Expression, double&gt;();
        match.Case&lt;Num&gt;((x) =&gt; x.Value);
        match.Case&lt;Mul&gt;((x) =&gt; Calculate(x.Left) * Calculate(x.Right));
        match.Case&lt;Add&gt;((x) =&gt; Calculate(x.Left) + Calculate(x.Right));
        return match.Eval(exp);
    }

    public static void Main(string[] args)
    {
        Expression tree = new Add(new Add(new Num(1), new Num(2)), new Mul(new Num(3), new Num(4)));
        double x = Calculate(tree) // = 15
    }
}

abstract class Expression
{
    public double Value;
}

abstract class BinaryExpression : Expression
{
    public Expression Left;
    public Expression Right;

    public BinaryExpression(Expression left, Expression right)
    {
        Left = left; Right = right;
    }
}

class Add : BinaryExpression
{
    public Add(Expression left, Expression right)
        : base(left, right)
    {
    }
}

class Mul : BinaryExpression
{
    public Mul(Expression left, Expression right)
        : base(left, right)
    {
    }
}

class Num : Expression
{
    public Num(double x)
    {
        Value = x;
    }
}
In your Match class, I would mark the two private dictionaries as readonly to signify intent and keep them from being assigned to accidentally anywhere else:

private readonly Dictionary&lt;Type, Delegate&gt; funcs =
    new Dictionary&lt;Type, Delegate&gt;();

private readonly Dictionary&lt;TIn, TReturn&gt; values =
    new Dictionary&lt;TIn, TReturn&gt;();


Secondly, I'd design to interfaces and make them IDictionaries as good OO practice:

private readonly IDictionary&lt;Type, Delegate&gt; funcs =
    new Dictionary&lt;Type, Delegate&gt;();

private readonly IDictionary&lt;TIn, TReturn&gt; values =
    new Dictionary&lt;TIn, TReturn&gt;();


In your example classes, you should forego public member data and use properties accessing backing fields (also marked readonly):

abstract class Expression
{
    private readonly double _Value;

    protected Expression(double value)
    {
        this._Value = value;
    }

    public double Value
    {
        get
        {
            return this._Value;
        }
    }
}

abstract class BinaryExpression : Expression
{
    private readonly Expression _Left;

    private readonly Expression _Right;

    public BinaryExpression(Expression left, Expression right) : base(default(double))
    {
        this._Left = left;
        this._Right = right;
    }

    public Expression Left
    {
        get
        {
            return this._Left;
        }
    }

    public Expression Right
    {
        get
        {
            return this._Right;
        }
    }
}

class Add : BinaryExpression
{
    public Add(Expression left, Expression right) : base(left, right)
    {
    }
}

class Mul : BinaryExpression
{
    public Mul(Expression left, Expression right) : base(left, right)
    {
    }
}

class Num : Expression
{
    public Num(double x) : base(x)
    {
    }
}