public int LastIndexOf(T item, int index, int count, IEqualityComparer <T> equalityComparer)
        {
            Requires.Range(index >= 0, nameof(index));
            Requires.Range(count >= 0 && count <= this.Count, nameof(count));
            Requires.Argument(
                index - count + 1 >= 0,
                nameof(count),
                "The specified {0} and {1} do not produce a enumerable range.",
                nameof(index),
                nameof(count));

            equalityComparer = equalityComparer ?? EqualityComparer <T> .Default;
            using (var enumerator = new ImmutableTrieList <T> .Enumerator(this, startIndex: index, count: count, reversed: true))
            {
                while (enumerator.MoveNext())
                {
                    if (equalityComparer.Equals(item, enumerator.Current))
                    {
                        return(index);
                    }

                    index--;
                }
            }

            return(-1);
        }
        /// <summary>
        /// Retrieves all the elements that match the conditions defined by the specified
        /// predicate.
        /// </summary>
        /// <param name="match">
        /// The <see cref="Predicate{T}"/> delegate that defines the conditions of the elements
        /// to search for.
        /// </param>
        /// <returns>
        /// A <see cref="ImmutableTrieList{T}"/> containing all the elements that match
        /// the conditions defined by the specified predicate, if found; otherwise, an
        /// empty <see cref="ImmutableTrieList{T}"/>.
        /// </returns>
        public ImmutableTrieList <T> FindAll(Predicate <T> match)
        {
            Requires.NotNull(match, nameof(match));
            if (this.IsEmpty)
            {
                return(ImmutableTrieList <T> .Empty);
            }

            List <T> list = null;

            foreach (var item in this)
            {
                if (match(item))
                {
                    if (list == null)
                    {
                        list = new List <T>();
                    }

                    list.Add(item);
                }
            }

            return(list != null?
                   ImmutableTrieList.CreateRange(list) :
                       ImmutableTrieList <T> .Empty);
        }
            /// <summary>
            /// Creates an immutable list based on the contents of this instance.
            /// </summary>
            /// <returns>An immutable list.</returns>
            /// <remarks>
            /// This method is an O(1) operation.
            /// </remarks>
            public ImmutableTrieList <T> ToImmutable()
            {
                if (Owner == null)
                {
                    // Nothing changes, return the original list
                    return(_originalList);
                }

                Owner = null;
                return(_originalList = new ImmutableTrieList <T>(Origin, Capacity, Count, Shift, Root, Tail));
            }
        /// <summary>
        /// Searches for an element that matches the conditions defined by the specified
        /// predicate, and returns the last occurrence within the entire <see cref="ImmutableTrieList{T}"/>.
        /// </summary>
        /// <param name="match">
        /// The <see cref="Predicate{T}"/> delegate that defines the conditions of the element
        /// to search for.
        /// </param>
        /// <returns>
        /// The last element that matches the conditions defined by the specified predicate,
        /// if found; otherwise, the default value for type <typeparamref name="T"/>.
        /// </returns>
        public T FindLast(Predicate <T> match)
        {
            Requires.NotNull(match, nameof(match));
            using (var enumerator = new ImmutableTrieList <T> .Enumerator(this, reversed: true))
            {
                while (enumerator.MoveNext())
                {
                    if (match(enumerator.Current))
                    {
                        return(enumerator.Current);
                    }
                }
            }

            return(default(T));
        }
        /// <summary>
        /// Copies a range of elements from the <see cref="ImmutableTrieList{T}"/> to
        /// a compatible one-dimensional array, starting at the specified index of the
        /// target array.
        /// </summary>
        /// <param name="index">
        /// The zero-based index in the source <see cref="ImmutableTrieList{T}"/> at
        /// which copying begins.
        /// </param>
        /// <param name="array">
        /// The one-dimensional <see cref="Array"/> that is the destination of the elements
        /// copied from <see cref="ImmutableTrieList{T}"/>. The <see cref="Array"/> must have
        /// zero-based indexing.
        /// </param>
        /// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
        /// <param name="count">The number of elements to copy.</param>
        public void CopyTo(int index, T[] array, int arrayIndex, int count)
        {
            Requires.NotNull(array, nameof(array));
            Requires.Range(index >= 0, nameof(index));
            Requires.Range(count >= 0, nameof(count));
            Requires.Range(index + count <= this.Count, nameof(count));
            Requires.Range(arrayIndex >= 0, nameof(arrayIndex));
            Requires.Range(arrayIndex + count <= array.Length, nameof(arrayIndex));

            using (var enumerator = new ImmutableTrieList <T> .Enumerator(this, startIndex: index, count: count))
            {
                while (enumerator.MoveNext())
                {
                    array[arrayIndex++] = enumerator.Current;
                }
            }
        }
        /// <summary>
        /// Searches for an element that matches the conditions defined by the specified
        /// predicate, and returns the zero-based index of the last occurrence within
        /// the range of elements in the <see cref="ImmutableTrieList{T}"/> that contains
        /// the specified number of elements and ends at the specified index.
        /// </summary>
        /// <param name="startIndex">The zero-based starting index of the backward search.</param>
        /// <param name="count">The number of elements in the section to search.</param>
        /// <param name="match">
        /// The <see cref="Predicate{T}"/> delegate that defines the conditions of the element
        /// to search for.
        /// </param>
        /// <returns>
        /// The zero-based index of the last occurrence of an element that matches the
        /// conditions defined by <paramref name="match"/>, if found; otherwise, -1.
        /// </returns>
        public int FindLastIndex(int startIndex, int count, Predicate <T> match)
        {
            Requires.NotNull(match, nameof(match));
            Requires.Range(startIndex >= 0, nameof(startIndex));
            Requires.Range(count <= this.Count, nameof(count));
            Requires.Range(startIndex - count + 1 >= 0, nameof(startIndex));

            using (var enumerator = new ImmutableTrieList <T> .Enumerator(this, startIndex: startIndex, count: count, reversed: true))
            {
                int index = startIndex;
                while (enumerator.MoveNext())
                {
                    if (match(enumerator.Current))
                    {
                        return(index);
                    }

                    index--;
                }
            }

            return(-1);
        }
        public int IndexOf(T item, int index, int count, IEqualityComparer <T> equalityComparer)
        {
            Requires.Range(index >= 0, nameof(index));
            Requires.Range(count >= 0, nameof(count));
            Requires.Range(count <= this.Count, nameof(count));
            Requires.Range(index + count <= this.Count, nameof(count));

            equalityComparer = equalityComparer ?? EqualityComparer <T> .Default;
            using (var enumerator = new ImmutableTrieList <T> .Enumerator(this, startIndex: index, count: count))
            {
                while (enumerator.MoveNext())
                {
                    if (equalityComparer.Equals(item, enumerator.Current))
                    {
                        return(index);
                    }

                    index++;
                }
            }

            return(-1);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ImmutableTrieListBuilderDebuggerProxy{T}"/> class.
 /// </summary>
 /// <param name="builder">The list to display in the debugger</param>
 public ImmutableTrieListBuilderDebuggerProxy(ImmutableTrieList <T> .Builder builder)
 {
     Requires.NotNull(builder, nameof(builder));
     _list = builder;
 }
 internal Builder(ImmutableTrieList <T> immutable)
     : base(immutable.Origin, immutable.Capacity, immutable.Count, immutable.Shift, immutable.Root, immutable.Tail)
 {
     Version       = 0;
     _originalList = immutable;
 }