Created
September 2, 2013 02:26
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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