LINQ method that selects an item based on previous one my requirement is to implement a way to filter a collection of elements based on a value of previous one. 
For example to only select a number that is larger than the previous one. I don't currently know of any LINQ method that would allow me to do such a thing, so I decided to create one. 

This is a code I have so far:

        public static IEnumerable&lt;T&gt; WherePrevious&lt;T&gt;(this IEnumerable&lt;T&gt; collection, Func&lt;T, T, bool&gt; predicate)
    {
        if (collection == null) throw new ArgumentNullException(nameof(collection));
        if (predicate == null) throw new ArgumentNullException(nameof(predicate));

        T previous = default(T);
        bool firstIteration = true;

        foreach (var item in collection)
        {
            if (firstIteration)
            {
                previous = item;
                firstIteration = false;
                yield return item;
            }
            else
            {
                if (predicate(previous, item))
                {
                    yield return item;
                }

                previous = item;
            }
        }
    }


Are there any ways to improve my code in terms of performance, readability or more generalization to make?

For example I'm not sure if it's clear to the caller of the method what the predicate inputs actually are
Linq Zip came to mind in order to map the items in pairs and then apply the predicate.

public static IEnumerable&lt;T&gt; WherePrevious&lt;T&gt;(this IEnumerable&lt;T&gt; collection, Func&lt;T, T, bool&gt; predicate) {
    if (collection == null) throw new ArgumentNullException(nameof(collection));
    if (predicate == null) throw new ArgumentNullException(nameof(predicate));
    if(!collection.Any()) yield break;

    yield return collection.First();

    var items = collection
        .Zip(collection.Skip(1), (previous, item) =&gt; (previous, item))
        .Where(zip =&gt; predicate(zip.previous, zip.item))
        .Select(zip =&gt; zip.item);

    foreach(var item in items)
        yield return item;
}


The following test was used to demonstrate the example given in the original question.

[TestClass]
public class FilterTest {
    [TestMethod]
    public void WherePreviousTest() {
        //Arrange
        var numbers = new[] { 1, 5, 8, 7, 12, 8, 5 };
        var expected = new[] { 1, 5, 8, 12 };

        //Act
        var actual = numbers.WherePrevious((first, second) =&gt; second &gt; first).ToArray();

        //Assert
        actual.ShouldAllBeEquivalentTo(expected);
    }
}


The body of the created extension method could have been done on its own, but creating the extension method allowed for a cleaner approach.

While I would say it is easier to read IMO, technically you will be enumerating the list more than once, which makes this not as efficient as your one pass through.

That then lead me to rethink my approach. After reviewing the source code for Enumerable.Zip and realizing your approach had the right idea I refactored the code to use the enumerator of the collection.

public static IEnumerable&lt;T&gt; WherePrevious&lt;T&gt;(this IEnumerable&lt;T&gt; collection, Func&lt;T, T, bool&gt; predicate) {
    if (collection == null) throw new ArgumentNullException(nameof(collection));
    if (predicate == null) throw new ArgumentNullException(nameof(predicate));
    return WherePreviousIterator(collection, predicate);
}

private static IEnumerable&lt;T&gt; WherePreviousIterator&lt;T&gt;(IEnumerable&lt;T&gt; collection, Func&lt;T, T, bool&gt; predicate) {
    using (var e = collection.GetEnumerator()) {
        if (e.MoveNext()) {
            var previous = e.Current;
            yield return previous;
            while (e.MoveNext()) {
                var item = e.Current;
                if (predicate(previous, item))
                    yield return item;
                previous = item;
            }
        }
        yield break;
    }
}


Which actually performed not that much better than the previous suggestion using Zip when run against the same test above.