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);
}
}
}