Skip to content

Instantly share code, notes, and snippets.

@spirit11
Last active August 11, 2017 06:54
Show Gist options
  • Save spirit11/ac6af74e86663a6bd11a8489862e4925 to your computer and use it in GitHub Desktop.
Save spirit11/ac6af74e86663a6bd11a8489862e4925 to your computer and use it in GitHub Desktop.
using System;
/// <summary>
/// Extension class for pattern matching workaround in older version of C#
/// </summary>
public static class PatternMatchExtension
{
public interface IMatcher<T>
where T : class
{
/// <summary>
/// Invokes Action when pattern object is of type TV
/// </summary>
/// <typeparam name="TV">subtype of T</typeparam>
/// <param name="Action">Action to invoke</param>
/// <returns></returns>
IMatcher<T> Case<TV>(Action<TV> Action)
where TV : T;
/// <summary>
/// Invokes Action when other matches hasn't succeed
/// </summary>
/// <param name="Action">Action to invoke</param>
void Default(Action<T> Action);
}
/// <summary>
/// Starts the chain of matching cases. Call Case and Default methods of returned object.
/// </summary>
/// <typeparam name="T">Object type</typeparam>
/// <param name="Object">Object for pattern matching</param>
/// <returns>Pattern matching monad <see cref="IMatcher{T}"/></returns>
public static IMatcher<T> Match<T>(this T Object)
where T : class
{
return new Matcher<T>(Object);
}
private class Matcher<T> : IMatcher<T>
where T : class
{
public Matcher(T Object)
{
this.obj = Object;
}
public IMatcher<T> Case<TV>(Action<TV> Action)
where TV : T
{
if (obj is TV)
{
Action((TV)obj);
return new Bypass<T>();
}
return this;
}
public void Default(Action<T> Action)
{
Action(obj);
}
private T obj;
}
private class Bypass<T> : IMatcher<T>
where T : class
{
public IMatcher<T> Case<TV>(Action<TV> Action)
where TV : T
{
return this;
}
public void Default(Action<T> Action)
{
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment