DotNext by .NET Foundation and Contributors

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

 ReadOnlyListView<TInput, TOutput>

public struct ReadOnlyListView<TInput, TOutput> : IReadOnlyList<TOutput>, IEnumerable<TOutput>, IEnumerable, IReadOnlyCollection<TOutput>, IEquatable<ReadOnlyListView<TInput, TOutput>>
Represents lazily converted read-only list.
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Collections.Generic { [StructLayout(LayoutKind.Auto)] [NullableContext(1)] [Nullable(0)] public readonly struct ReadOnlyListView<[Nullable(2)] TInput, [Nullable(2)] TOutput> : IReadOnlyList<TOutput>, IEnumerable<TOutput>, IEnumerable, IReadOnlyCollection<TOutput>, IEquatable<ReadOnlyListView<TInput, TOutput>> { private readonly IReadOnlyList<TInput> source; private readonly Func<TInput, TOutput> mapper; public TOutput this[int index] { get { if (source == null) throw new ArgumentOutOfRangeException("index"); return mapper(source[index]); } } public int Count { get { IReadOnlyList<TInput> readOnlyList = source; if (readOnlyList == null) return 0; return readOnlyList.Count; } } public ReadOnlyListView(IReadOnlyList<TInput> list, Func<TInput, TOutput> mapper) { if (list == null) throw new ArgumentNullException("list"); source = list; if (mapper == null) throw new ArgumentNullException("mapper"); this.mapper = mapper; } public ReadOnlyListView(IReadOnlyList<TInput> list, Converter<TInput, TOutput> mapper) { this = new ReadOnlyListView<TInput, TOutput>(list, Unsafe.As<Func<TInput, TOutput>>((object)mapper)); } public IEnumerator<TOutput> GetEnumerator() { IReadOnlyList<TInput> readOnlyList = source; bool flag = (readOnlyList == null || readOnlyList.Count == 0) ? true : false; if (!flag && mapper != null) return Enumerable.Select<TInput, TOutput>((IEnumerable<TInput>)source, mapper).GetEnumerator(); return Enumerable.Empty<TOutput>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private bool Equals([In] [IsReadOnly] ref ReadOnlyListView<TInput, TOutput> other) { if (source == other.source) return mapper == other.mapper; return false; } public bool Equals([Nullable(new byte[] { 0, 1, 1 })] ReadOnlyListView<TInput, TOutput> other) { return Equals(ref other); } public override int GetHashCode() { return RuntimeHelpers.GetHashCode(source) ^ mapper.GetHashCode(); } [NullableContext(2)] public override bool Equals(object other) { if (!(other is ReadOnlyListView<TInput, TOutput>)) return object.Equals(source, other); ReadOnlyListView<TInput, TOutput> other2 = (ReadOnlyListView<TInput, TOutput>)other; return Equals(ref other2); } public static bool operator ==([In] [IsReadOnly] [Nullable(new byte[] { 0, 1, 1 })] ref ReadOnlyListView<TInput, TOutput> first, [In] [IsReadOnly] [Nullable(new byte[] { 0, 1, 1 })] ref ReadOnlyListView<TInput, TOutput> second) { return first.Equals(ref second); } public static bool operator !=([In] [IsReadOnly] [Nullable(new byte[] { 0, 1, 1 })] ref ReadOnlyListView<TInput, TOutput> first, [In] [IsReadOnly] [Nullable(new byte[] { 0, 1, 1 })] ref ReadOnlyListView<TInput, TOutput> second) { return !first.Equals(ref second); } } }