#nullable enable // 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.Runtime.CompilerServices; namespace System.Runtime.InteropServices { /// /// An unsafe class that provides a set of methods to access the underlying data representations of collections. /// public static class CollectionsMarshal { private class ListView { public T[] _items; public int _size; public int _version; private static readonly T[] s_emptyArray = new T[0]; public void EnsureCapacity(int min) { if (this._items.Length >= min) return; int num = this._items.Length == 0 ? 4 : this._items.Length * 2; if ((uint)num > 2146435071U) num = 2146435071; if (num < min) num = min; this.Capacity = num; } public int Capacity { get => this._items.Length; set { if (value < this._size) throw new ArgumentOutOfRangeException(nameof(value), "Capacity is set too small"); if (value == this._items.Length) return; if (value > 0) { T[] destinationArray = new T[value]; if (this._size > 0) Array.Copy((Array)this._items, 0, (Array)destinationArray, 0, this._size); this._items = destinationArray; } else this._items = s_emptyArray; } } } /// /// Get a view over a 's data. /// Items should not be added or removed from the while the is in use. /// /// The list to get the data view over. /// The type of the elements in the list. public static Span AsSpan(this List? list) { if (list is null) return default; var listView = Unsafe.As>(list); return listView._items.AsSpan(); } public static void SetCount(this List list, int count) { ForceSetCount(list, count); } /// /// Sets the count of the to the specified value. /// /// The list to set the count of. /// The value to set the list's count to. /// The type of the elements in the list. /// /// is . /// /// /// is negative. /// /// /// When increasing the count, uninitialized data is being exposed. /// public static void ForceSetCount(this List list, int count) { if (list is null) throw new NullReferenceException("list is null."); var listView = Unsafe.As>(list); if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count), $"{nameof(count)} must be more than 0!"); } listView._version++; if (count > list.Capacity) { listView.EnsureCapacity(count); } else if (count < listView._size && RuntimeHelpers.IsReferenceOrContainsReferences()) { Array.Clear(listView._items, count, listView._size - count); } listView._size = count; } } }