DotNext by .NET Foundation and Contributors

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

 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)] [NullableContext(1)] [Nullable(0)] public struct Enumerator : IEnumerator<Enumerator, T> { private readonly IProducerConsumerCollection<T> collection; private T current; public T 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; } } 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 Collection.ToClassicEnumerator<Enumerator, T>(GetEnumerator()); } IEnumerator IEnumerable.GetEnumerator() { return Collection.ToClassicEnumerator<Enumerator, T>(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; } [return: Nullable(new byte[] { 0, 1 })] public static Optional<T> FirstOrNone<[Nullable(2)] T>(this IEnumerable<T> collection) { if (collection == null) throw new ArgumentNullException("collection"); List<T> list = collection as List<T>; if (list != null) return CollectionsMarshal.AsSpan(list).FirstOrNone<T>(null); T[] array = collection as T[]; if (array != null) return array.FirstOrNone<T>(null); string text = collection as string; if (text != null) return Unsafe.BitCast<Optional<char>, Optional<T>>(text.FirstOrNone<char>(null)); LinkedList<T> linkedList = collection as LinkedList<T>; if (linkedList != null) { LinkedListNode<T> first = linkedList.First; return (first != null) ? ((Optional<T>)first.Value) : Optional<T>.None; } IList<T> list2 = collection as IList<T>; if (list2 != null) return (((ICollection<T>)list2).Count > 0) ? ((Optional<T>)list2[0]) : Optional<T>.None; IReadOnlyList<T> readOnlyList = collection as IReadOnlyList<T>; if (readOnlyList != null) return (((IReadOnlyCollection<T>)readOnlyList).Count > 0) ? ((Optional<T>)readOnlyList[0]) : Optional<T>.None; return <FirstOrNone>g__FirstOrNoneSlow|11_0(collection); } [return: Nullable(new byte[] { 0, 1 })] public static Optional<T> LastOrNone<[Nullable(2)] T>(this IEnumerable<T> collection) { if (collection == null) throw new ArgumentNullException("collection"); List<T> list = collection as List<T>; if (list != null) return Span.LastOrNone<T>(CollectionsMarshal.AsSpan(list)); T[] array = collection as T[]; if (array != null) return Span.LastOrNone<T>(array); string text = collection as string; if (text != null) return Unsafe.BitCast<Optional<char>, Optional<T>>(Span.LastOrNone<char>(text)); LinkedList<T> linkedList = collection as LinkedList<T>; if (linkedList != null) { LinkedListNode<T> last = linkedList.Last; return (last != null) ? ((Optional<T>)last.Value) : Optional<T>.None; } IList<T> list2 = collection as IList<T>; if (list2 != null) { Optional<T> result; if (((ICollection<T>)list2).Count <= 0) result = Optional<T>.None; else { IList<T> list3 = list2; result = list3[((ICollection<T>)list3).Count - 1]; } return result; } IReadOnlyList<T> readOnlyList = collection as IReadOnlyList<T>; if (readOnlyList != null) { Optional<T> result2; if (((IReadOnlyCollection<T>)readOnlyList).Count <= 0) result2 = Optional<T>.None; else { IReadOnlyList<T> readOnlyList2 = readOnlyList; result2 = readOnlyList2[((IReadOnlyCollection<T>)readOnlyList2).Count - 1]; } return result2; } return <LastOrNone>g__LastOrNoneSlow|12_0(collection); } public static bool ElementAt<[Nullable(2)] T>(this IEnumerable<T> collection, int index, [MaybeNullWhen(false)] out T element) { if (collection == null) throw new ArgumentNullException("collection"); 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|13_0(linkedList, index, out element); IList<T> list2 = collection as IList<T>; if (list2 != null) return <ElementAt>g__ListElementAt|13_2(list2, index, out element); IReadOnlyList<T> readOnlyList = collection as IReadOnlyList<T>; if (readOnlyList != null) return <ElementAt>g__ReadOnlyListElementAt|13_3(readOnlyList, index, out element); return <ElementAt>g__ElementAtSlow|13_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); } [NullableContext(0)] [return: Nullable(1)] public static IEnumerator<T> ToClassicEnumerator<TEnumerator, [Nullable(2)] T>(this TEnumerator enumerator) where TEnumerator : struct, IEnumerator<TEnumerator, T> { return ((IEnumerator<TEnumerator, T>)).ToEnumerator(enumerator); } [NullableContext(0)] [return: Nullable(1)] public static IAsyncEnumerator<T> ToAsyncEnumerator<TEnumerator, [Nullable(2)] T>(this TEnumerator enumerator, CancellationToken token) where TEnumerator : struct, IEnumerator<TEnumerator, T> { return ((IEnumerator<TEnumerator, T>)).ToEnumerator(enumerator, token); } } }