DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="5.3.1" />

 Collection

public static class Collection
Provides utility methods to work with collections.
using DotNext.Buffers; using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace DotNext.Collections.Generic { [NullableContext(1)] [Nullable(0)] public static class Collection { [StructLayout(LayoutKind.Auto)] [NullableContext(0)] public readonly struct ConsumingEnumerable<[Nullable(2)] T> : IEnumerable<T>, IEnumerable { [StructLayout(LayoutKind.Auto)] public struct Enumerator : IEnumerator<T>, IEnumerator, IDisposable { private readonly IProducerConsumerCollection<T> collection; private T current; [Nullable(1)] public T Current { [IsReadOnly] [NullableContext(1)] get { return current; } } [Nullable(2)] object IEnumerator.Current { [IsReadOnly] get { return Current; } } internal Enumerator(IProducerConsumerCollection<T> collection) { this.collection = collection; current = default(T); } public bool MoveNext() { return collection?.TryTake(out current) ?? false; } [IsReadOnly] void IEnumerator.Reset() { throw new NotSupportedException(); } void IDisposable.Dispose() { this = default(Enumerator); } } private readonly IProducerConsumerCollection<T> collection; internal ConsumingEnumerable(IProducerConsumerCollection<T> collection) { this.collection = collection; } public Enumerator GetEnumerator() { return new Enumerator(collection); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private sealed class NotNullEnumerable<T> : IEnumerable<T>, IEnumerable where T : class { private sealed class Enumerator : Disposable, IEnumerator<T>, IEnumerator, IDisposable { private readonly IEnumerator<T> enumerator; private T current; public T Current { get { T val = current; if (val == null) throw new InvalidOperationException(); return val; } } object IEnumerator.Current { get { return Current; } } internal Enumerator(IEnumerable<T> enumerable) { enumerator = enumerable.GetEnumerator(); } public bool MoveNext() { while (enumerator.MoveNext()) { T val = enumerator.Current; if (val != null) { current = val; return true; } } return false; } public void Reset() { enumerator.Reset(); } protected override void Dispose(bool disposing) { if (disposing) { current = null; enumerator.Dispose(); } base.Dispose(disposing); } } private readonly IEnumerable<T> enumerable; internal NotNullEnumerable(IEnumerable<T> enumerable) { this.enumerable = enumerable; } public IEnumerator<T> GetEnumerator() { return new Enumerator(enumerable); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } [return: Nullable(new byte[] { 0, 1 })] public static MemoryOwner<T> Copy<[Nullable(2)] T>(this IEnumerable<T> enumerable, int sizeHint = 0, [Nullable(new byte[] { 2, 1 })] MemoryAllocator<T> allocator = null) { ArgumentNullException.ThrowIfNull((object)enumerable, "enumerable"); ArgumentOutOfRangeException.ThrowIfNegative<int>(sizeHint, "sizeHint"); List<T> list = enumerable as List<T>; if (list != null) return CollectionsMarshal.AsSpan(list).Copy(allocator); T[] array = enumerable as T[]; if (array != null) return Span.Copy(array, allocator); string text = enumerable as string; if (text != null) return Unsafe.BitCast<MemoryOwner<char>, MemoryOwner<T>>(text.AsSpan().Copy(Unsafe.As<MemoryAllocator<char>>((object)allocator))); if (!(enumerable is ArraySegment<T>)) { ICollection<T> collection = enumerable as ICollection<T>; if (collection != null) return (collection.Count == 0) ? default(MemoryOwner<T>) : ((allocator == null) ? <Copy>g__CopyCollection|0_0(collection) : <Copy>g__CopySlow|0_1(collection, collection.Count, allocator)); IReadOnlyCollection<T> readOnlyCollection = enumerable as IReadOnlyCollection<T>; if (readOnlyCollection != null) return (readOnlyCollection.Count == 0) ? default(MemoryOwner<T>) : <Copy>g__CopySlow|0_1(enumerable, readOnlyCollection.Count, allocator); return <Copy>g__CopySlow|0_1(enumerable, <Copy>g__GetSize|0_2(enumerable, sizeHint), allocator); } ArraySegment<T> segment = (ArraySegment<T>)enumerable; return segment.AsSpan().Copy(allocator); } [return: Nullable(new byte[] { 0, 1 })] public static ConsumingEnumerable<T> GetConsumer<[Nullable(2)] T>(this IProducerConsumerCollection<T> collection) { if (collection == null) throw new ArgumentNullException("collection"); return new ConsumingEnumerable<T>(collection); } [return: Nullable(new byte[] { 0, 1, 1 })] public static ReadOnlyCollectionView<TInput, TOutput> Convert<[Nullable(2)] TInput, [Nullable(2)] TOutput>(this IReadOnlyCollection<TInput> collection, Converter<TInput, TOutput> converter) { return new ReadOnlyCollectionView<TInput, TOutput>(collection, converter); } public static T[] ToArray<[Nullable(2)] T>(ICollection<T> collection) { int count = collection.Count; T[] array; if (count == 0) array = Array.Empty<T>(); else { array = GC.AllocateUninitializedArray<T>(count, false); collection.CopyTo(array, 0); } return array; } public unsafe static T[] ToArray<[Nullable(2)] T>(IReadOnlyCollection<T> collection) { int count = collection.Count; if (count == 0) return Array.Empty<T>(); T[] array = GC.AllocateUninitializedArray<T>(count, false); UIntPtr uIntPtr = (UIntPtr)(void*)null; foreach (T item in (IEnumerable<T>)collection) { T[] array2 = array; UIntPtr intPtr = uIntPtr; uIntPtr = (UIntPtr)(void*)((long)(ulong)intPtr + 1); array2[(ulong)intPtr] = item; } return array; } public static void AddAll<[Nullable(2)] T>(this ICollection<T> collection, IEnumerable<T> items) { if (collection == null) throw new ArgumentNullException("collection"); List<T> list = collection as List<T>; if (list == null) { HashSet<T> hashSet = collection as HashSet<T>; if (hashSet != null) hashSet.UnionWith(items); else items.ForEach(collection.Add); } else list.AddRange(items); } public static int SequenceHashCode<[Nullable(2)] T>(this IEnumerable<T> sequence, bool salted = true) { int num = sequence.Aggregate(-910176598, (int hash, T obj) => hash * -1521134295 + ((obj != null) ? EqualityComparer<T>.Default.GetHashCode(obj) : 0)); if (!salted) return num; return num * -1521134295 + RandomExtensions.BitwiseHashSalt; } internal static bool SequenceEqual<T>(IEnumerable<T> first, IEnumerable<T> second) { if (first != null) { if (second != null) return first.SequenceEqual(second); return false; } return second == null; } public static void ForEach<[Nullable(2)] T>(this IEnumerable<T> collection, Action<T> action) { List<T> list = collection as List<T>; if (list == null) { T[] array = collection as T[]; if (array == null) { if (collection is ArraySegment<T>) { ArraySegment<T> segment = (ArraySegment<T>)collection; Span.ForEach(segment.AsSpan(), action); } else { LinkedList<T> linkedList = collection as LinkedList<T>; if (linkedList == null) { string text = collection as string; if (text != null) Span.ForEach(text.AsSpan(), Unsafe.As<Action<char>>((object)action)); else <ForEach>g__ForEachSlow|9_0(collection, action); } else <ForEach>g__ForEachNode|9_1(linkedList, action); } } else Array.ForEach(array, action); } else Span.ForEach(CollectionsMarshal.AsSpan(list), action); } [AsyncStateMachine(typeof(<ForEachAsync>d__10<>))] public static ValueTask ForEachAsync<[Nullable(2)] T>(this IEnumerable<T> collection, Func<T, CancellationToken, ValueTask> action, CancellationToken token = default(CancellationToken)) { <ForEachAsync>d__10<T> stateMachine = default(<ForEachAsync>d__10<T>); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create(); stateMachine.collection = collection; stateMachine.action = action; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } public static bool ElementAt<[Nullable(2)] T>(this IEnumerable<T> collection, int index, [MaybeNullWhen(false)] out T element) { List<T> list = collection as List<T>; if (list != null) return Span.ElementAt(CollectionsMarshal.AsSpan(list), index, out element); T[] array = collection as T[]; if (array != null) return Span.ElementAt(array, index, out element); LinkedList<T> linkedList = collection as LinkedList<T>; if (linkedList != null) return <ElementAt>g__NodeValueAt|11_0(linkedList, index, out element); IList<T> list2 = collection as IList<T>; if (list2 != null) return <ElementAt>g__ListElementAt|11_2(list2, index, out element); IReadOnlyList<T> readOnlyList = collection as IReadOnlyList<T>; if (readOnlyList != null) return <ElementAt>g__ReadOnlyListElementAt|11_3(readOnlyList, index, out element); return <ElementAt>g__ElementAtSlow|11_1(collection, index, out element); } public static IEnumerable<T> SkipNulls<T>([Nullable(new byte[] { 1, 2 })] this IEnumerable<T> collection) where T : class { return new NotNullEnumerable<T>(collection); } public static string ToString<[Nullable(2)] T>(this IEnumerable<T> collection, string delimiter, string ifEmpty = "") { string text = string.Join(delimiter, collection); if (text == null || text.Length <= 0) return ifEmpty; return text; } public static IEnumerable<T> Prepend<[Nullable(2)] T>(this IEnumerable<T> collection, params T[] items) { return items.Concat(collection); } public static IEnumerable<T> Append<[Nullable(2)] T>(this IEnumerable<T> collection, params T[] items) { return collection.Concat(items); } public static IAsyncEnumerable<T> ToAsyncEnumerable<[Nullable(2)] T>(this IEnumerable<T> enumerable) { if (enumerable == null) throw new ArgumentNullException("enumerable"); return new AsyncEnumerable.Proxy<T>(enumerable); } } }