示例#1
0
            // Copy all of the elements in the iterator, finishing before indexAfterCopy.
            // If indexAfterCopy is array.Length, we'll finish copying at the end of the array.
            // The reason we take an ending index as opposed to a starting one is because
            // we only hold a reference to the most recently concat'd collection. So to start
            // copying at a certain index, we'd have to re-walk the linked list of iterators
            // all the way back to the least recent one, and repeat that for all of the
            // collections we hold.
            private void CopyBefore(TSource[] array, int indexAfterCopy)
            {
                Debug.Assert(array != null);
                Debug.Assert(indexAfterCopy >= 0 && indexAfterCopy <= array.Length);
                Debug.Assert(indexAfterCopy >= Count);

                // Copy the items from this collection, which is the last
                // one that was concatenated
                int copied = _next.Count;

                _next.CopyTo(array, indexAfterCopy - copied);

                ConcatIterator <TSource> previous = _previous;

                ConcatNCollectionIterator <TSource> previousN;

                while ((previousN = previous as ConcatNCollectionIterator <TSource>) != null)
                {
                    checked
                    {
                        copied += previousN._next.Count;
                    }
                    previousN._next.CopyTo(array, indexAfterCopy - copied);
                    previous = previousN._previous;
                }

                // We've reached the first 2 collections that were concatenated
                var previous2 = (Concat2CollectionIterator <TSource>)previous;

                copied += previous2.Count;
                Debug.Assert(copied == Count); // We should have copied all the elements

                previous2.CopyTo(array, indexAfterCopy - copied);
            }
示例#2
0
 internal ConcatNEnumerableIterator(ConcatIterator <TSource> previousConcat, IEnumerable <TSource> next, int nextIndex)
 {
     Debug.Assert(previousConcat != null);
     Debug.Assert(next != null);
     Debug.Assert(nextIndex >= 2);
     _previousConcat = previousConcat;
     _next           = next;
     _nextIndex      = nextIndex;
 }
示例#3
0
            internal ConcatNCollectionIterator(ConcatIterator <TSource> previous, ICollection <TSource> next, int nextIndex)
            {
                Debug.Assert(previous != null);
                Debug.Assert(previous is Concat2CollectionIterator <TSource> || previous is ConcatNCollectionIterator <TSource>);
                Debug.Assert(next != null);
                Debug.Assert(nextIndex >= 2);

                _previous  = previous;
                _next      = next;
                _nextIndex = nextIndex;
            }
示例#4
0
            /// <summary>
            /// Initializes a new instance of the <see cref="ConcatNIterator{TSource}"/> class.
            /// </summary>
            /// <param name="tail">The linked list of previous sources.</param>
            /// <param name="head">The source associated with this iterator.</param>
            /// <param name="headIndex">The logical index associated with this iterator.</param>
            /// <param name="hasOnlyCollections">
            /// <c>true</c> if all sources this iterator concatenates implement <see cref="ICollection{TSource}"/>;
            /// otherwise, <c>false</c>.
            /// </param>
            internal ConcatNIterator(ConcatIterator <TSource> tail, IEnumerable <TSource> head, int headIndex, bool hasOnlyCollections)
            {
                Debug.Assert(tail != null);
                Debug.Assert(head != null);
                Debug.Assert(headIndex >= 2);

                _tail               = tail;
                _head               = head;
                _headIndex          = headIndex;
                _hasOnlyCollections = hasOnlyCollections;
            }
示例#5
0
            internal override IEnumerable <TSource> GetEnumerable(int index)
            {
                if (index > _nextIndex)
                {
                    return(null);
                }

                // Walk back through the chain of ConcatNIterators looking for the one
                // that has its _nextIndex equal to index.  If we don't find one, then it
                // must be prior to any of them, so call GetEnumerable on the previous
                // Concat2Iterator.  This avoids a deep recursive call chain.
                ConcatNEnumerableIterator <TSource> current = this;

                while (true)
                {
                    if (index == current._nextIndex)
                    {
                        return(current._next);
                    }

                    ConcatIterator <TSource> previous = current._previousConcat;

                    var previousEnumerables = previous as ConcatNEnumerableIterator <TSource>;
                    if (previousEnumerables != null)
                    {
                        current = previousEnumerables;
                        continue;
                    }

                    var previousCollections = previous as ConcatNCollectionIterator <TSource>;
                    if (previousCollections != null)
                    {
                        // Since ConcatNCollectionIterator.GetEnumerable does not call into this method,
                        // it is safe to call GetEnumerable on it here. It also makes things faster, since
                        // the above type-cast will only ever be run once per call of this method.
                        return(previousCollections.GetEnumerable(index));
                    }

                    // We've reached the tail of the linked list, which contains the first 2 enumerables.
                    Debug.Assert(previous is Concat2EnumerableIterator <TSource> || previous is Concat2CollectionIterator <TSource>);
                    Debug.Assert(index == 0 || index == 1);
                    return(previous.GetEnumerable(index));
                }
            }