| | 1 | | using System.Collections; |
| | 2 | |
|
| | 3 | | namespace MoreStructures.Utilities; |
| | 4 | |
|
| | 5 | | /// <summary> |
| | 6 | | /// A <see cref="IValueEnumerable{T}"/> implementation, wrapping a generic <see cref="IEnumerable{T}"/>. |
| | 7 | | /// </summary> |
| | 8 | | /// <typeparam name="T">The type of objects of the wrapped enumerable.</typeparam> |
| | 9 | | /// <remarks> |
| | 10 | | /// Useful to preserve equality by value in records and other value structures which contain enumerable objects. |
| | 11 | | /// <br/> |
| | 12 | | /// It doesn't cache nor enumerate the underlying <see cref="Enumerable"/> unless <see cref="GetEnumerator"/> or a |
| | 13 | | /// method requiring <see cref="Enumerable"/> items is called. |
| | 14 | | /// </remarks> |
| | 15 | | public class ValueEnumerable<T> : IValueEnumerable<T> |
| | 16 | | { |
| 392352 | 17 | | private IEnumerable<T> Enumerable { get; } |
| | 18 | |
|
| | 19 | | /// <summary> |
| | 20 | | /// Builds a <see cref="ValueEnumerable{T}"/> around the provided <paramref name="enumerable"/>. |
| | 21 | | /// </summary> |
| | 22 | | /// <param name="enumerable">The enumerable to wrap.</param> |
| | 23 | | /// <remarks> |
| | 24 | | /// Time and Space Complexity is O(1), as this constructor doesn't enumerate <paramref name="enumerable"/>. |
| | 25 | | /// </remarks> |
| 16068 | 26 | | public ValueEnumerable(IEnumerable<T> enumerable) |
| 16068 | 27 | | { |
| 16068 | 28 | | Enumerable = enumerable is ValueEnumerable<T> { Enumerable: var underlyingEnumerable} |
| 16068 | 29 | | ? underlyingEnumerable |
| 16068 | 30 | | : enumerable; |
| 16068 | 31 | | } |
| | 32 | |
|
| | 33 | | /// <inheritdoc/> |
| | 34 | | public IEnumerator<T> GetEnumerator() => |
| 391530 | 35 | | Enumerable.GetEnumerator(); |
| | 36 | |
|
| | 37 | | /// <inheritdoc/> |
| | 38 | | IEnumerator IEnumerable.GetEnumerator() => |
| 3 | 39 | | (Enumerable as IEnumerable).GetEnumerator(); |
| | 40 | |
|
| | 41 | | /// <inheritdoc path="//*[not(self::remarks)]"/> |
| | 42 | | /// <remarks> |
| | 43 | | /// In the specific case, equality is based on the |
| | 44 | | /// <see cref="Enumerable.SequenceEqual{TSource}(IEnumerable{TSource}, IEnumerable{TSource})"/> of the wrapped |
| | 45 | | /// <see cref="IEnumerable{T}"/> objects. |
| | 46 | | /// <br/> |
| | 47 | | /// Therefore, Time Complexity is O(n * Te) and Space Complexity is O(Se), where n is the number of elements of |
| | 48 | | /// the longest <see cref="Enumerable"/> and Te/Se are the time and space costs of |
| | 49 | | /// <see cref="object.Equals(object?)"/> of two <typeparamref name="T"/> instances. |
| | 50 | | /// </remarks> |
| | 51 | | public override bool Equals(object? obj) => |
| 328 | 52 | | obj is ValueEnumerable<T> other && Enumerable.SequenceEqual(other.Enumerable); |
| | 53 | |
|
| | 54 | | /// <inheritdoc path="//*[not(self::remarks)]"/> |
| | 55 | | /// <remarks> |
| | 56 | | /// In the specific case, the hash is calculated as an aggregation of the hash codes of the items of the |
| | 57 | | /// wrapped <see cref="Enumerable"/> object. |
| | 58 | | /// <br/> |
| | 59 | | /// Therefore, Time Complexity is O(n * Te) and Space Complexity is O(Se), where n is the number of elements of |
| | 60 | | /// the longest <see cref="Enumerable"/> and Te/Se are the time and space costs of |
| | 61 | | /// <see cref="object.GetHashCode()"/> of a <typeparamref name="T"/> instance. |
| | 62 | | /// </remarks> |
| | 63 | | public override int GetHashCode() => |
| 946 | 64 | | Enumerable.Aggregate(0.GetHashCode(), (acc, item) => acc ^ (item?.GetHashCode() ?? 0)); |
| | 65 | |
|
| | 66 | | /// <inheritdoc path="//*[not(self::remarks)]"/> |
| | 67 | | /// <remarks> |
| | 68 | | /// In the specific case, the string calculation is delegated to the wrapped <see cref="IEnumerable{T}"/> |
| | 69 | | /// object. |
| | 70 | | /// <br/> |
| | 71 | | /// Therefore, Time and Space Complexity are the ones of the specific implementation of |
| | 72 | | /// <see cref="object.ToString()"/> of the underlying <see cref="Enumerable"/>. |
| | 73 | | /// </remarks> |
| | 74 | | public override string ToString() => |
| 3 | 75 | | Enumerable.ToString()!; |
| | 76 | | } |