| File: Internal\ImmutableArray.cs | Web Access |
| Project: src\runtime\src\libraries\System.Threading.Tasks.Dataflow\src\System.Threading.Tasks.Dataflow.csproj (System.Threading.Tasks.Dataflow) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // ImmutableArray.cs // // // An immutable data structure that supports adding, removing, and enumerating elements. // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Collections.Generic; using System.Diagnostics; namespace System.Threading.Tasks.Dataflow.Internal { // NOTE: We use a very simple ImmutableArray implementation rather than taking a dependency // on the full System.Collections.Immutable.dll, which contains much more than we need // for such a simple purpose. /// <summary>Provides a simple, immutable array.</summary> /// <typeparam name="T">Specifies the type of the data stored in the array.</typeparam> [DebuggerDisplay("Count = {Count}")] internal readonly struct ImmutableArray<T> { /// <summary>An empty array.</summary> #pragma warning disable CA1825 // avoid the extra generic instantiation for Array.Empty<T>() private static readonly ImmutableArray<T> s_empty = new ImmutableArray<T>(new T[0]); #pragma warning restore CA1825 /// <summary>The immutable data in this array instance.</summary> private readonly T[] _array; /// <summary>Gets the empty array.</summary> public static ImmutableArray<T> Empty { get { return s_empty; } } /// <summary>Initializes the immutable array with the specified elements.</summary> /// <param name="elements">The element array to use for this array's data.</param> private ImmutableArray(T[] elements) { Debug.Assert(elements != null, "Requires an array to wrap."); _array = elements; } /// <summary>Creates a new immutable array from this array and the additional element.</summary> /// <param name="item">The item to add.</param> /// <returns>The new array.</returns> public ImmutableArray<T> Add(T item) { // Copy the elements from this array and the item // to a new array that's returned. var newArray = new T[_array.Length + 1]; Array.Copy(_array, newArray, _array.Length); newArray[newArray.Length - 1] = item; return new ImmutableArray<T>(newArray); } /// <summary>Creates a new immutable array from this array and without the specified element.</summary> /// <param name="item">The item to remove.</param> /// <returns>The new array.</returns> public ImmutableArray<T> Remove(T item) { // Get the index of the element. If it's not in the array, just return this array. int index = Array.IndexOf(_array, item); if (index < 0) return this; // It's in the array, so if it's the only one, just return the empty array if (_array.Length == 1) return Empty; // Otherwise, copy the other elements to a new array that's returned. var newArray = new T[_array.Length - 1]; Array.Copy(_array, newArray, index); Array.Copy(_array, index + 1, newArray, index, _array.Length - index - 1); return new ImmutableArray<T>(newArray); } /// <summary>Gets the number of elements in this array.</summary> public int Count { get { return _array.Length; } } /// <summary>Gets whether the array contains the specified item.</summary> /// <param name="item">The item to lookup.</param> /// <returns>true if the array contains the item; otherwise, false.</returns> public bool Contains(T item) { return Array.IndexOf(_array, item) >= 0; } /// <summary>Returns an enumerator that iterates through the collection.</summary> public IEnumerator<T> GetEnumerator() { return ((IEnumerable<T>)_array).GetEnumerator(); } /// <summary>Returns the contents of the collection as an array.</summary> /// <returns>An array containing the contents of this collection.</returns> public T[] ToArray() { return _array.Length == 0 ? s_empty._array : (T[])_array.Clone(); } } }