Skip to content

Instantly share code, notes, and snippets.

@alexbihary
Created September 2, 2013 02:26
Show Gist options
  • Save alexbihary/6408732 to your computer and use it in GitHub Desktop.
Save alexbihary/6408732 to your computer and use it in GitHub Desktop.
Pattern Matching (or Type-like switch statement) implementation From http://stackoverflow.com/questions/156467/switch-pattern-matching-idea/7301884#7301884
public class PatternMatcher<Output>
{
List<Tuple<Predicate<Object>, Func<Object, Output>>> cases = new List<Tuple<Predicate<object>,Func<object,Output>>>();
public PatternMatcher() { }
public PatternMatcher<Output> Case(Predicate<Object> condition, Func<Object, Output> function)
{
cases.Add(new Tuple<Predicate<Object>, Func<Object, Output>>(condition, function));
return this;
}
public PatternMatcher<Output> Case<T>(Predicate<T> condition, Func<T, Output> function)
{
return Case(
o => o is T && condition((T)o),
o => function((T)o));
}
public PatternMatcher<Output> Case<T>(Func<T, Output> function)
{
return Case(
o => o is T,
o => function((T)o));
}
public PatternMatcher<Output> Case<T>(Predicate<T> condition, Output o)
{
return Case(condition, x => o);
}
public PatternMatcher<Output> Case<T>(Output o)
{
return Case<T>(x => o);
}
public PatternMatcher<Output> Default(Func<Object, Output> function)
{
return Case(o => true, function);
}
public PatternMatcher<Output> Default(Output o)
{
return Default(x => o);
}
public Output Match(Object o)
{
foreach (var tuple in cases)
if (tuple.Item1(o))
return tuple.Item2(o);
throw new Exception("Failed to match");
}
}
public enum EngineType
{
Diesel,
Gasoline
}
public class Bicycle
{
public int Cylinders;
}
public class Car
{
public EngineType EngineType;
public int Doors;
}
public class MotorCycle
{
public int Cylinders;
}
public void Run()
{
var getRentPrice = new PatternMatcher<int>()
.Case<MotorCycle>(bike => 100 + bike.Cylinders * 10)
.Case<Bicycle>(30)
.Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
.Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
.Default(0);
var vehicles = new object[] {
new Car { EngineType = EngineType.Diesel, Doors = 2 },
new Car { EngineType = EngineType.Diesel, Doors = 4 },
new Car { EngineType = EngineType.Gasoline, Doors = 3 },
new Car { EngineType = EngineType.Gasoline, Doors = 5 },
new Bicycle(),
new MotorCycle { Cylinders = 2 },
new MotorCycle { Cylinders = 3 },
};
foreach (var v in vehicles)
{
Console.WriteLine("Vehicle of type {0} costs {1} to rent", v.GetType(), getRentPrice.Match(v));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment