DotNext by Roman Sakno

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

 ReadOnlyListView<T>

Represents read-only view of the mutable list.
using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace DotNext.Collections.Generic { public readonly struct ReadOnlyListView<T> : IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T>, IEquatable<ReadOnlyListView<T>> { private readonly IList<T> source; public int Count => source.Count; public T this[int index] { get { return source[index]; } } public ReadOnlyListView(IList<T> list) { if (list == null) throw new ArgumentNullException("list"); source = list; } public int IndexOf(T item) { return source.IndexOf(item); } public bool Contains(T item) { return source.Contains(item); } public IEnumerator<T> GetEnumerator() { return source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Equals(ReadOnlyListView<T> other) { return source == other.source; } public override int GetHashCode() { return RuntimeHelpers.GetHashCode(source); } public override bool Equals(object other) { if (!(other is ReadOnlyCollectionView<T>)) return object.Equals(source, other); ReadOnlyCollectionView<T> readOnlyCollectionView = (ReadOnlyCollectionView<T>)other; return Equals(readOnlyCollectionView); } public static bool operator ==(ReadOnlyListView<T> first, ReadOnlyListView<T> second) { return first.Equals(second); } public static bool operator !=(ReadOnlyListView<T> first, ReadOnlyListView<T> second) { return !first.Equals(second); } } }