File: System\Collections\Immutable\ImmutableQueue.cs
Web Access
Project: src\src\libraries\System.Collections.Immutable\src\System.Collections.Immutable.csproj (System.Collections.Immutable)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
 
namespace System.Collections.Immutable
{
    /// <summary>
    /// A set of initialization methods for instances of <see cref="ImmutableQueue{T}"/>.
    /// </summary>
    public static class ImmutableQueue
    {
        /// <summary>
        /// Returns an empty collection.
        /// </summary>
        /// <typeparam name="T">The type of items stored by the collection.</typeparam>
        /// <returns>The immutable collection.</returns>
        public static ImmutableQueue<T> Create<T>()
        {
            return ImmutableQueue<T>.Empty;
        }
 
        /// <summary>
        /// Creates a new immutable collection prefilled with the specified item.
        /// </summary>
        /// <typeparam name="T">The type of items stored by the collection.</typeparam>
        /// <param name="item">The item to prepopulate.</param>
        /// <returns>The new immutable collection.</returns>
        public static ImmutableQueue<T> Create<T>(T item) => ImmutableQueue<T>.Empty.Enqueue(item);
 
        /// <summary>
        /// Creates a new immutable queue from the specified items.
        /// </summary>
        /// <typeparam name="T">The type of items to store in the queue.</typeparam>
        /// <param name="items">The enumerable to copy items from.</param>
        /// <returns>The new immutable queue.</returns>
        public static ImmutableQueue<T> CreateRange<T>(IEnumerable<T> items)
        {
            Requires.NotNull(items, nameof(items));
 
            if (items is T[] array)
            {
                return Create(items: array);
            }
 
            using (IEnumerator<T> e = items.GetEnumerator())
            {
                if (!e.MoveNext())
                {
                    return ImmutableQueue<T>.Empty;
                }
 
                ImmutableStack<T> forwards = ImmutableStack.Create(e.Current);
                ImmutableStack<T> backwards = ImmutableStack<T>.Empty;
 
                while (e.MoveNext())
                {
                    backwards = backwards.Push(e.Current);
                }
 
                return new ImmutableQueue<T>(forwards: forwards, backwards: backwards);
            }
        }
 
        /// <summary>
        /// Creates a new immutable queue from the specified items.
        /// </summary>
        /// <typeparam name="T">The type of items to store in the queue.</typeparam>
        /// <param name="items">The array to copy items from.</param>
        /// <returns>The new immutable queue.</returns>
        public static ImmutableQueue<T> Create<T>(params T[] items)
        {
            Requires.NotNull(items, nameof(items));
 
            return Create((ReadOnlySpan<T>)items);
        }
 
        /// <summary>
        /// Creates a new immutable queue that contains the specified array of items.
        /// </summary>
        /// <typeparam name="T">The type of items in the immutable queue.</typeparam>
        /// <param name="items">A span that contains the items to prepopulate the queue with.</param>
        /// <returns>A new immutable queue that contains the specified items.</returns>
        public static ImmutableQueue<T> Create<T>(params ReadOnlySpan<T> items)
        {
            if (items.IsEmpty)
            {
                return ImmutableQueue<T>.Empty;
            }
 
            ImmutableStack<T> forwards = ImmutableStack<T>.Empty;
 
            for (int i = items.Length - 1; i >= 0; i--)
            {
                forwards = forwards.Push(items[i]);
            }
 
            return new ImmutableQueue<T>(forwards: forwards, backwards: ImmutableStack<T>.Empty);
        }
 
        /// <summary>
        /// Retrieves the item at the head of the queue, and returns a queue with the head element removed.
        /// </summary>
        /// <typeparam name="T">The type of elements stored in the queue.</typeparam>
        /// <param name="queue">The queue to dequeue from.</param>
        /// <param name="value">Receives the value from the head of the queue.</param>
        /// <returns>The new queue with the head element removed.</returns>
        /// <exception cref="InvalidOperationException">Thrown when the stack is empty.</exception>
        public static IImmutableQueue<T> Dequeue<T>(this IImmutableQueue<T> queue, out T value)
        {
            Requires.NotNull(queue, nameof(queue));
 
            value = queue.Peek();
            return queue.Dequeue();
        }
    }
}