public static IEnumerable <Sandwich <TSource> > Sandwich <TSource>(this IEnumerable <TSource> source)
    {
        var withExtras = source.AddFakeSlices();

        var sandwiches = withExtras
                         .Skip(1)
                         .Zip(withExtras, (curr, prev) => new
        {
            Current  = curr,
            Previous = prev
        })
                         .Zip(withExtras.Skip(2), (curr, next) => new
        {
            curr.Previous,
            curr.Current,
            Next = next
        });

        foreach (var item in sandwiches)
        {
            var sandwich = new Sandwich <TSource>()
            {
                Previous = item.Previous,
                Current  = item.Current,
                Next     = item.Next
            };

            yield return(sandwich);
        }
    }
    public static IEnumerable <TResult> Sandwich <TSource, TResult>(this IEnumerable <TSource> source, Func <TSource, TSource, TSource, TResult> projection) where TSource : class
    {
        var withExtras = source.AddFakeSlices();

        var prevCurrNext = withExtras
                           .Skip(1)
                           .Zip(withExtras, (curr, prev) => new
        {
            Current  = curr,
            Previous = prev
        })
                           .Zip(withExtras.Skip(2), (curr, next) => new
        {
            curr.Previous,
            curr.Current,
            Next = next
        });

        foreach (var item in prevCurrNext)
        {
            yield return(projection(item.Previous, item.Current, item.Next));
        }
    }