Last active
September 19, 2025 10:30
-
-
Save RichardD2/eaee2550edfe848ba2daf47ab6c7e8dc to your computer and use it in GitHub Desktop.
EquatableArray
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.ComponentModel; | |
| using System.Runtime.CompilerServices; | |
| namespace NBS.Collections.Generic; | |
| [CollectionBuilder(typeof(EquatableArray), nameof(EquatableArray.Create))] | |
| public readonly struct EquatableArray<T>(T[] values, IEqualityComparer<T>? comparer = default) : IReadOnlyList<T>, IEquatable<EquatableArray<T>> | |
| { | |
| private readonly T[] _values = values; | |
| private readonly IEqualityComparer<T> _comparer = comparer ?? EqualityComparer<T>.Default; | |
| public int Length => _values?.Length ?? 0; | |
| int IReadOnlyCollection<T>.Count => Length; | |
| public T this[int index] => _values is null ? throw new IndexOutOfRangeException() : _values[index]; | |
| public Enumerator GetEnumerator() => new(_values); | |
| IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator(); | |
| IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
| // Required to support collection expressions: | |
| [Obsolete("This method is not supported.")] | |
| [EditorBrowsable(EditorBrowsableState.Never)] | |
| public void Add(T item) => throw new NotSupportedException(); | |
| public override int GetHashCode() | |
| { | |
| if (_values is null or []) return 0; | |
| HashCode code = new(); | |
| for (int index = 0; index < _values.Length; index++) | |
| { | |
| code.Add(_values[index], _comparer); | |
| } | |
| return code.ToHashCode(); | |
| } | |
| public override bool Equals(object? obj) => obj is EquatableArray<T> other && Equals(other); | |
| public bool Equals(EquatableArray<T> other) | |
| { | |
| if (Length != other.Length) return false; | |
| if (_values is null or []) return true; | |
| for (int index = 0; index < _values.Length; index++) | |
| { | |
| if (!_comparer.Equals(_values[index], other._values[index])) | |
| { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| public static bool operator ==(EquatableArray<T> left, EquatableArray<T> right) => left.Equals(right); | |
| public static bool operator !=(EquatableArray<T> left, EquatableArray<T> right) => !left.Equals(right); | |
| public struct Enumerator(T[]? array) : IEnumerator<T> | |
| { | |
| private readonly T[] _array = array ?? []; | |
| private int _current = -1; | |
| public T Current | |
| { | |
| get | |
| { | |
| if (_current < 0 || _current >= _array.Length) throw new InvalidOperationException(); | |
| return _array[_current]; | |
| } | |
| } | |
| object? IEnumerator.Current => Current; | |
| public bool MoveNext() | |
| { | |
| if (_current < _array.Length) | |
| { | |
| _current++; | |
| return _current < _array.Length; | |
| } | |
| return false; | |
| } | |
| public void Reset() | |
| { | |
| _current = -1; | |
| } | |
| public void Dispose() | |
| { | |
| } | |
| } | |
| } | |
| public static class EquatableArray | |
| { | |
| public static EquatableArray<T> Create<T>(params ReadOnlySpan<T> values) => new(values.ToArray()); | |
| public static EquatableArray<T> Create<T>(T[] values) => new(values); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment