DotNext by Roman Sakno

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

 Sequence

public static class Sequence
Various methods to work with classes implementing IEnumerable<T> interface.
using DotNext.Collections.Generic; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public static class Sequence { [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.Nullable(0)] public struct LimitedEnumerator<[System.Runtime.CompilerServices.Nullable(2)] T> : IEnumerator<T>, IEnumerator, IDisposable { private readonly IEnumerator<T> enumerator; private readonly bool disposeEnumerator; private int count; public T Current { [IsReadOnly] get { return enumerator.Current; } } [System.Runtime.CompilerServices.Nullable(2)] object IEnumerator.Current { [IsReadOnly] [System.Runtime.CompilerServices.NullableContext(2)] get { return Current; } } internal LimitedEnumerator(IEnumerator<T> enumerator, int limit, bool leaveOpen) { this.enumerator = enumerator; disposeEnumerator = !leaveOpen; count = limit; } public bool MoveNext() { if (count-- > 0) return enumerator.MoveNext(); return false; } [IsReadOnly] public void Reset() { enumerator?.Reset(); } public void Dispose() { if (disposeEnumerator) enumerator?.Dispose(); this = default(LimitedEnumerator<T>); } } [System.Runtime.CompilerServices.Nullable(0)] private sealed class NotNullEnumerable<T> : IEnumerable<T>, IEnumerable where T : class { [System.Runtime.CompilerServices.Nullable(0)] private sealed class Enumerator : IEnumerator<T>, IEnumerator, IDisposable { [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] private readonly IEnumerator<T> enumerator; [System.Runtime.CompilerServices.Nullable(2)] 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([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] 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(); } void IDisposable.Dispose() { current = null; enumerator.Dispose(); } } [System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] private readonly IEnumerable<T> enumerable; internal NotNullEnumerable([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] IEnumerable<T> enumerable) { this.enumerable = enumerable; } public IEnumerator<T> GetEnumerator() { return new Enumerator(enumerable); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private const int HashSalt = -1521134295; [System.Runtime.CompilerServices.NullableContext(2)] private static int GetHashCode(int hash, object obj) { return (hash * -1521134295 + obj?.GetHashCode()).GetValueOrDefault(); } public static int SequenceHashCode([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] this IEnumerable<object> sequence, bool salted = true) { int num = sequence.Aggregate(-910176598, GetHashCode); if (!salted) return num; return num * -1521134295 + RandomExtensions.BitwiseHashSalt; } internal static bool SequenceEqual([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] IEnumerable<object> first, [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] IEnumerable<object> second) { if (first != null && second != null) return first.SequenceEqual(second); return first == second; } public static void ForEach<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, Action<T> action) { ValueAction<T> action2 = new ValueAction<T>(action, true); collection.ForEach(ref action2); } public static void ForEach<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, [In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ref ValueAction<T> action) { foreach (T item in collection) { action.Invoke(item); } } [System.Runtime.CompilerServices.NullableContext(0)] public static T? FirstOrNull<T>([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 0 })] this IEnumerable<T> seq) where T : struct { using (IEnumerator<T> enumerator = seq.GetEnumerator()) return enumerator.MoveNext() ? new T?(enumerator.Current) : null; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public static Optional<T> FirstOrEmpty<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> seq) { using (IEnumerator<T> enumerator = seq.GetEnumerator()) return enumerator.MoveNext() ? ((Optional<T>)enumerator.Current) : Optional<T>.Empty; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public static Optional<T> FirstOrEmpty<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> seq, [In] [IsReadOnly] [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ref ValueFunc<T, bool> filter) { foreach (T item in seq) { if (filter.Invoke(item)) return item; } return Optional<T>.Empty; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public static Optional<T> FirstOrEmpty<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> seq, Predicate<T> filter) { ValueFunc<T, bool> filter2 = filter.AsValueFunc(true); return seq.FirstOrEmpty(ref filter2); } public static bool Skip<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerator<T> enumerator, int count) { while (count > 0) { if (!enumerator.MoveNext()) return false; count--; } return true; } [System.Runtime.CompilerServices.NullableContext(0)] public static bool Skip<TEnumerator, [System.Runtime.CompilerServices.Nullable(2)] T>(ref TEnumerator enumerator, int count) where TEnumerator : struct, IEnumerator<T> { while (count > 0) { if (!enumerator.MoveNext()) return false; count--; } return true; } private static bool ElementAt<[System.Runtime.CompilerServices.Nullable(2)] T>(this IList<T> list, int index, [NotNullWhen(true)] out T element) { if (index >= 0 && index < ((ICollection<T>)list).Count) { element = list[index]; return true; } element = default(T); return false; } private static bool ElementAt<[System.Runtime.CompilerServices.Nullable(2)] T>(this IReadOnlyList<T> list, int index, [NotNullWhen(true)] out T element) { if (index >= 0 && index < ((IReadOnlyCollection<T>)list).Count) { element = list[index]; return true; } element = default(T); return false; } public static bool ElementAt<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, int index, [NotNullWhen(true)] out T element) { IList<T> list = collection as IList<T>; if (list != null) return list.ElementAt(index, out element); IReadOnlyList<T> readOnlyList = collection as IReadOnlyList<T>; if (readOnlyList != null) return readOnlyList.ElementAt(index, out element); using (IEnumerator<T> enumerator = collection.GetEnumerator()) { enumerator.Skip(index); if (!enumerator.MoveNext()) { element = default(T); return false; } element = enumerator.Current; return true; } } public static IEnumerable<T> SkipNulls<T>([System.Runtime.CompilerServices.Nullable(new byte[] { 1, 2 })] this IEnumerable<T> collection) where T : class { return new NotNullEnumerable<T>(collection); } public static string ToString<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, string delimiter, string ifEmpty = "") { return string.Join(delimiter, collection).IfNullOrEmpty(ifEmpty); } public static IEnumerable<T> Singleton<[System.Runtime.CompilerServices.Nullable(2)] T>(T item) { return List.Singleton(item); } public static IEnumerable<T> Prepend<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, params T[] items) { return items.Concat(collection); } public static IEnumerable<T> Append<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerable<T> collection, params T[] items) { return collection.Concat(items); } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public static LimitedEnumerator<T> Limit<[System.Runtime.CompilerServices.Nullable(2)] T>(this IEnumerator<T> enumerator, int count, bool leaveOpen = false) { return new LimitedEnumerator<T>(enumerator, count, leaveOpen); } } }