using System.Collections.Generic;
public static void Main()
.When(i => i % 3 == 0).Then(i => Console.WriteLine("fizz"))
.When(i => i % 5 == 0).Then(i => Console.WriteLine("buzz"))
.Otherwise(i => Console.WriteLine(i))
public static class EnumerableExtensions {
public static IWhen<T> When<T>(this IEnumerable<T> source, Func<T, bool> test) {
var temp = new When<T>(source, test);
public interface IWhen<T> {
IThen<T> Then(Action<T> action);
public interface IThen<T> : IRun {
IWhen<T> When(Func<T, bool> test);
IRun Otherwise(Action<T> action);
public interface IRule<T> {
Func<T, bool> Predicate { get; }
Action<T> Invoke { get; }
public class Rule<T> : IRule<T> {
public Rule(Func<T, bool> predicate, Action<T> action) {
this.Predicate = predicate;
public Func<T, bool> Predicate { get; private set; }
public Action<T> Invoke { get; private set; }
public class Then<T> : IThen<T> {
private Queue<IRule<T>> rules = new Queue<IRule<T>>();
private IEnumerable<T> source;
public Then(IEnumerable<T> source, Queue<IRule<T>> rules) {
public IWhen<T> When(Func<T, bool> test) {
var temp = new When<T>(source, test, rules);
foreach (var item in source) {
var rule = rules.FirstOrDefault(r => r.Predicate(item));
if (rule == null) continue;
public IRun Otherwise(Action<T> action) {
var rule = new Rule<T>(s => true, action);
return new Then<T>(source, rules);
public class When<T> : IWhen<T> {
private Queue<IRule<T>> rules;
private Func<T, bool> test;
private IEnumerable<T> source;
public When(IEnumerable<T> source, Func<T, bool> test, Queue<IRule<T>> rules = null) {
this.rules = rules ?? new Queue<IRule<T>>();
public IThen<T> Then(Action<T> action) {
var rule = new Rule<T>(test, action);
var then = new Then<T>(source, rules);