Enumerator
Various methods to work with classes implementing IEnumerable<T> interface.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace DotNext.Collections.Generic
{
[NullableContext(1)]
[Nullable(0)]
public static class Enumerator
{
[StructLayout(LayoutKind.Auto)]
[NullableContext(0)]
public struct LimitedEnumerator<[Nullable(2)] T> : IEnumerator<T>, IEnumerator, IDisposable
{
private readonly IEnumerator<T> enumerator;
private readonly bool disposeEnumerator;
private int count;
[Nullable(1)]
public T Current {
[IsReadOnly]
[NullableContext(1)]
get {
return enumerator.Current;
}
}
[Nullable(2)]
object IEnumerator.Current {
[IsReadOnly]
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>);
}
}
public static bool Skip<[Nullable(2)] T>(this IEnumerator<T> enumerator, int count)
{
while (count > 0) {
if (!enumerator.MoveNext())
return false;
count--;
}
return true;
}
[NullableContext(0)]
public static bool Skip<TEnumerator, [Nullable(2)] T>(ref TEnumerator enumerator, int count) where TEnumerator : struct, IEnumerator<T>
{
while (count > 0) {
if (!enumerator.MoveNext())
return false;
count--;
}
return true;
}
[return: Nullable(new byte[] {
0,
1
})]
public static LimitedEnumerator<T> Limit<[Nullable(2)] T>(this IEnumerator<T> enumerator, int count, bool leaveOpen = false)
{
return new LimitedEnumerator<T>(enumerator, count, leaveOpen);
}
public static IEnumerator<T> ToEnumerator<[Nullable(2)] T>([Nullable(new byte[] {
0,
1
})] ReadOnlyMemory<T> memory)
{
if (!memory.IsEmpty) {
if (!MemoryMarshal.TryGetArray(memory, out ArraySegment<T> segment))
return <ToEnumerator>g__ToEnumeratorSlow|3_0(memory);
return segment.GetEnumerator();
}
return Enumerable.Empty<T>().GetEnumerator();
}
public static IEnumerator<T> ToEnumerator<[Nullable(2)] T>([In] [IsReadOnly] [Nullable(new byte[] {
0,
1
})] ref ReadOnlySequence<T> sequence)
{
if (!sequence.IsEmpty) {
if (!sequence.IsSingleSegment)
return <ToEnumerator>g__ToEnumeratorSlow|4_0(sequence.GetEnumerator());
return ToEnumerator(sequence.First);
}
return Enumerable.Empty<T>().GetEnumerator();
}
public static IAsyncEnumerator<T> GetAsyncEnumerator<[Nullable(2)] T>(this IEnumerable<T> enumerable, CancellationToken token = default(CancellationToken))
{
if (enumerable == null)
throw new ArgumentNullException("enumerable");
return new AsyncEnumerable.Proxy<T>.Enumerator(enumerable, token);
}
}
}