Custom implementation of the linq Zip operator for different length lists
public static class Impl
    {
        public static IEnumerable&lt;TResult&gt; ZipNew&lt;TFirst, TSecond, TResult&gt;(



Names? The class would be more descriptive as something like LinqExtensions; the method something like ZipLooped.




            using (IEnumerator&lt;TFirst&gt; iterator1 = first.GetEnumerator()) 
            using (IEnumerator&lt;TSecond&gt; iterator2 = second.GetEnumerator())
            {
                var i1 = true;
                var i2 = true;
                var i1Shorter = false;
                var i2Shorter = false;
                var firstRun = true;



The iterators have useful names, but what does i1 mean? And why five variables to track the state of two iterators? IMO it would be simpler as

                var firstEnded = false;
                var secondEnded = false;

                while (true) 
                {
                    if (!iterator1.MoveNext())
                    {
                        if (secondEnded) yield break;
                        firstEnded = true;
                        iterator1.Reset();
                        if (!iterator1.MoveNext()) yield break;
                    }
                    if (!iterator2.MoveNext())
                    {
                        if (firstEnded) yield break;
                        secondEnded = true;
                        iterator2.Reset();
                        if (!iterator2.MoveNext()) yield break;
                    }

                    yield return resultSelector(iterator1.Current, iterator2.Current); 
                }


and the almost repeated code might be worth pulling out as an inner method:

                var firstEnded = false;
                var secondEnded = false;

                bool advance&lt;T&gt;(IEnumerator&lt;T&gt; it, ref bool thisEnded, bool otherEnded)
                {
                    if (it.MoveNext()) return true;
                    // `it` has done a full cycle; if the other one has too, we've finished
                    if (otherEnded) return false;
                    thisEnded = true;
                    // Start again, although if `it` is empty we need to abort
                    it.Reset();
                    return it.MoveNext();
                }

                while (true)
                {
                    if (!advance(iterator1, ref firstEnded, secondEnded)) yield break;
                    if (!advance(iterator2, ref secondEnded, firstEnded)) yield break;
                    yield return resultSelector(iterator1.Current, iterator2.Current); 
                }




I notice that you've decided to yield break if either of the enumerables is empty. Would an exception be a better choice?