Как практика написания бедных API-интерфейсов, я думал, что сделаю следующую компиляцию и запуск:
static void Main(string[] args)
{
Enumerable.Range(1, 100)
.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))
.Run();
Console.ReadLine();
}
Идея .When
проверяет каждый элемент в перечислении, и если он передает предикат, чтобы запустить действие. Если предикат терпит неудачу, элемент передается по цепочке.
График, с которым я столкнулся, был:
public static class EnumerableExtensions
{
public static IConditionalEnumerable<T> When<T>(this IEnumerable<T> items, Predicate<T> test, Action<T> action)
{
}
public static IResolvedEnumerable<T> Then<T>(this IConditionalEnumerable<T> items, Predicate<T> test, Action<T> action)
{
}
public static void Run<T>(this IEnumerable<T> items)
{
foreach (var item in items) ;
}
}
public interface IConditionalEnumerable<T> : IEnumerable<T>
{
IResolvedEnumerable<T> Then<T>(IConditionalEnumerable<T> items, Action<T> action);
}
public interface IResolvedEnumerable<T> : IEnumerable<T>
{
IEnumerable<T> Otherwise(Action<T> behavior);
}
Я столкнулся с проблемой - When
не может foreach / yield return
внутри него, потому что тип возврата не является прямым IEnumerable<T>
(хотя он наследует его). Это заставило мысленный ключ в шестерню. Как выглядит реализация методов расширения?