|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | 3 |
|
4 | 4 | using System.Collections; |
5 | | -using System.Collections.Immutable; |
6 | 5 |
|
7 | 6 | namespace ModelContextProtocol.Analyzers; |
8 | 7 |
|
9 | 8 | /// <summary>An immutable, equatable array.</summary> |
10 | 9 | /// <typeparam name="T">The type of values in the array.</typeparam> |
11 | | -internal readonly struct EquatableArray<T> : IEquatable<EquatableArray<T>>, IEnumerable<T> |
12 | | - where T : IEquatable<T> |
| 10 | +internal readonly struct EquatableArray<T> : IEnumerable<T>, IEquatable<EquatableArray<T>> |
13 | 11 | { |
14 | | - /// <summary> |
15 | | - /// The underlying <typeparamref name="T"/> array. |
16 | | - /// </summary> |
17 | | - private readonly ImmutableArray<T> _array; |
| 12 | + /// <summary>The underlying <typeparamref name="T"/> array.</summary> |
| 13 | + private readonly T[]? _array; |
18 | 14 |
|
19 | 15 | /// <param name="source">The source to enumerate and wrap.</param> |
20 | | - public EquatableArray(IEnumerable<T> source) => _array = source.ToImmutableArray(); |
| 16 | + public EquatableArray(IEnumerable<T> source) => _array = source.ToArray(); |
21 | 17 |
|
22 | 18 | /// <param name="source">The source to wrap.</param> |
23 | | - public EquatableArray(ImmutableArray<T> array) => _array = array; |
| 19 | + public EquatableArray(T[] array) => _array = array; |
24 | 20 |
|
25 | | - /// <summary>An empty <see cref="EquatableArray{T}"/>.</summary> |
26 | | - public static EquatableArray<T> Empty => new(ImmutableArray<T>.Empty); |
27 | | - |
28 | | - /// <summary> |
29 | | - /// Gets a reference to an item at a specified position within the array. |
30 | | - /// </summary> |
| 21 | + /// <summary>Gets a reference to an item at a specified position within the array.</summary> |
31 | 22 | /// <param name="index">The index of the item to retrieve a reference to.</param> |
32 | 23 | /// <returns>A reference to an item at a specified position within the array.</returns> |
33 | | - public ref readonly T this[int index] => ref _array.ItemRef(index); |
34 | | - |
35 | | - /// <summary> |
36 | | - /// Gets a value indicating whether the current array is empty. |
37 | | - /// </summary> |
38 | | - public bool IsEmpty => _array.IsEmpty; |
| 24 | + public ref readonly T this[int index] => ref NonNullArray[index]; |
39 | 25 |
|
40 | | - /// <summary> |
41 | | - /// Gets a value indicating whether the current array is default or empty. |
42 | | - /// </summary> |
43 | | - public bool IsDefaultOrEmpty => _array.IsDefaultOrEmpty; |
| 26 | + /// <summary>Gets the backing array.</summary> |
| 27 | + private T[] NonNullArray => _array ?? []; |
44 | 28 |
|
45 | | - /// <summary> |
46 | | - /// Gets the length of the current array. |
47 | | - /// </summary> |
48 | | - public int Length => _array.Length; |
| 29 | + /// <summary>Gets the length of the current array.</summary> |
| 30 | + public int Length => NonNullArray.Length; |
49 | 31 |
|
50 | 32 | /// <inheritdoc/> |
51 | | - public bool Equals(EquatableArray<T> other) => _array.SequenceEqual(other._array); |
| 33 | + public bool Equals(EquatableArray<T> other) => NonNullArray.SequenceEqual(other.NonNullArray); |
52 | 34 |
|
53 | 35 | /// <inheritdoc/> |
54 | | - public override bool Equals(object? obj) => obj is EquatableArray<T> array && Equals(array); |
| 36 | + public override bool Equals(object? obj) => obj is EquatableArray<T> array && Equals(array); |
55 | 37 |
|
56 | 38 | /// <inheritdoc/> |
57 | 39 | public override int GetHashCode() |
58 | 40 | { |
59 | | - if (_array.IsDefault) |
60 | | - { |
61 | | - return 0; |
62 | | - } |
63 | | - |
64 | 41 | int hash = 17; |
65 | | - foreach (T item in _array) |
| 42 | + foreach (T item in NonNullArray) |
66 | 43 | { |
67 | 44 | hash = hash * 31 + (item?.GetHashCode() ?? 0); |
68 | 45 | } |
69 | 46 |
|
70 | 47 | return hash; |
71 | 48 | } |
72 | 49 |
|
73 | | - /// <summary> |
74 | | - /// Gets an <see cref="ImmutableArray{T}.Enumerator"/> value to traverse items in the current array. |
75 | | - /// </summary> |
76 | | - /// <returns>An <see cref="ImmutableArray{T}.Enumerator"/> value to traverse items in the current array.</returns> |
77 | | - public ImmutableArray<T>.Enumerator GetEnumerator() => _array.GetEnumerator(); |
78 | | - |
79 | 50 | /// <inheritdoc/> |
80 | | - IEnumerator<T> IEnumerable<T>.GetEnumerator() => ((IEnumerable<T>)_array).GetEnumerator(); |
| 51 | + IEnumerator<T> IEnumerable<T>.GetEnumerator() => ((IEnumerable<T>)NonNullArray).GetEnumerator(); |
81 | 52 |
|
82 | 53 | /// <inheritdoc/> |
83 | | - IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_array).GetEnumerator(); |
84 | | - |
85 | | - /// <summary> |
86 | | - /// Implicitly converts an <see cref="ImmutableArray{T}"/> to <see cref="EquatableArray{T}"/>. |
87 | | - /// </summary> |
88 | | - /// <returns>An <see cref="EquatableArray{T}"/> instance from a given <see cref="ImmutableArray{T}"/>.</returns> |
89 | | - public static implicit operator EquatableArray<T>(ImmutableArray<T> array) => new(array); |
90 | | - |
91 | | - /// <summary> |
92 | | - /// Implicitly converts an <see cref="EquatableArray{T}"/> to <see cref="ImmutableArray{T}"/>. |
93 | | - /// </summary> |
94 | | - /// <returns>An <see cref="ImmutableArray{T}"/> instance from a given <see cref="EquatableArray{T}"/>.</returns> |
95 | | - public static implicit operator ImmutableArray<T>(EquatableArray<T> array) => array._array; |
96 | | - |
97 | | - /// <summary> |
98 | | - /// Checks whether two <see cref="EquatableArray{T}"/> values are the same. |
99 | | - /// </summary> |
100 | | - /// <param name="left">The first <see cref="EquatableArray{T}"/> value.</param> |
101 | | - /// <param name="right">The second <see cref="EquatableArray{T}"/> value.</param> |
102 | | - /// <returns>Whether <paramref name="left"/> and <paramref name="right"/> are equal.</returns> |
103 | | - public static bool operator ==(EquatableArray<T> left, EquatableArray<T> right) => left.Equals(right); |
104 | | - |
105 | | - /// <summary> |
106 | | - /// Checks whether two <see cref="EquatableArray{T}"/> values are not the same. |
107 | | - /// </summary> |
108 | | - /// <param name="left">The first <see cref="EquatableArray{T}"/> value.</param> |
109 | | - /// <param name="right">The second <see cref="EquatableArray{T}"/> value.</param> |
110 | | - /// <returns>Whether <paramref name="left"/> and <paramref name="right"/> are not equal.</returns> |
111 | | - public static bool operator !=(EquatableArray<T> left, EquatableArray<T> right) => !left.Equals(right); |
| 54 | + IEnumerator IEnumerable.GetEnumerator() => NonNullArray.GetEnumerator(); |
112 | 55 | } |
0 commit comments