Custom implementation of the linq Zip operator for different length lists Based on my answer I have my implementation of linq Zip operator which operates on different length lists, and loops shortest list. 

My implementation:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SO
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            List&lt;String&gt; listA = new List&lt;string&gt; {"a", "b", "c", "d", "e", "f", "g"};
            List&lt;String&gt; listB = new List&lt;string&gt; {"1", "2", "3"};

            var mix = listA.ZipNew(listB, (l1, l2) =&gt; new[] {l1, l2}).SelectMany(x =&gt; x);

            foreach (var m in mix)
            {
                Console.WriteLine(m);
            }
        }
    }

    public static class Impl
    {               
        public static IEnumerable&lt;TResult&gt; ZipNew&lt;TFirst, TSecond, TResult&gt;( 
            this IEnumerable&lt;TFirst&gt; first, 
            IEnumerable&lt;TSecond&gt; second, 
            Func&lt;TFirst, TSecond, TResult&gt; resultSelector) 
        { 
            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;


                while(true) 
                {
                    i1 = iterator1.MoveNext();
                    i2 = iterator2.MoveNext();

                    if (!i1 &amp;&amp; (i1Shorter || firstRun))
                    {
                        iterator1.Reset();
                        i1 = iterator1.MoveNext();
                        i1Shorter = true;
                        firstRun = false;
                    }

                    if (!i2 &amp;&amp; (i2Shorter || firstRun))
                    {
                        iterator2.Reset();
                        i2 = iterator2.MoveNext();
                        i2Shorter = true;
                        firstRun = false;
                    }

                    if (!(i1 &amp;&amp; i2))
                    {
                        break;
                    }

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


And I wonder if this implementation could be improved somehow, what could be improved, for better readability or speed.
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?