Skip to content

Commit 0e2a94c

Browse files
authored
Merge pull request #190 from CommunityToolkit/dev/fix-indexof-return
Change IndexOf APIs to return -1 if not found
2 parents 5dc442a + 76f339f commit 0e2a94c

File tree

4 files changed

+48
-66
lines changed

4 files changed

+48
-66
lines changed

CommunityToolkit.HighPerformance/Extensions/ReadOnlySpanExtensions.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,7 @@ public static ReadOnlySpan2D<T> AsSpan2D<T>(this ReadOnlySpan<T> span, int offse
208208
/// <typeparam name="T">The type if items in the input <see cref="ReadOnlySpan{T}"/>.</typeparam>
209209
/// <param name="span">The input <see cref="ReadOnlySpan{T}"/> to calculate the index for.</param>
210210
/// <param name="value">The reference to the target item to get the index for.</param>
211-
/// <returns>The index of <paramref name="value"/> within <paramref name="span"/>.</returns>
212-
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="value"/> does not belong to <paramref name="span"/>.</exception>
211+
/// <returns>The index of <paramref name="value"/> within <paramref name="span"/>, or <c>-1</c>.</returns>
213212
[MethodImpl(MethodImplOptions.AggressiveInlining)]
214213
public static int IndexOf<T>(this ReadOnlySpan<T> span, in T value)
215214
{
@@ -221,7 +220,7 @@ public static int IndexOf<T>(this ReadOnlySpan<T> span, in T value)
221220

222221
if ((nuint)elementOffset >= (uint)span.Length)
223222
{
224-
SpanExtensions.ThrowArgumentOutOfRangeExceptionForInvalidReference();
223+
return -1;
225224
}
226225

227226
return (int)elementOffset;

CommunityToolkit.HighPerformance/Extensions/SpanExtensions.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ public static Span<TTo> Cast<TFrom, TTo>(this Span<TFrom> span)
146146
/// <typeparam name="T">The type if items in the input <see cref="Span{T}"/>.</typeparam>
147147
/// <param name="span">The input <see cref="Span{T}"/> to calculate the index for.</param>
148148
/// <param name="value">The reference to the target item to get the index for.</param>
149-
/// <returns>The index of <paramref name="value"/> within <paramref name="span"/>.</returns>
150-
/// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="value"/> does not belong to <paramref name="span"/>.</exception>
149+
/// <returns>The index of <paramref name="value"/> within <paramref name="span"/>, or <c>-1</c>.</returns>
151150
[MethodImpl(MethodImplOptions.AggressiveInlining)]
152151
public static int IndexOf<T>(this Span<T> span, ref T value)
153152
{
@@ -158,7 +157,7 @@ public static int IndexOf<T>(this Span<T> span, ref T value)
158157

159158
if ((nuint)elementOffset >= (uint)span.Length)
160159
{
161-
ThrowArgumentOutOfRangeExceptionForInvalidReference();
160+
return -1;
162161
}
163162

164163
return (int)elementOffset;
@@ -276,12 +275,4 @@ public static bool TryCopyTo<T>(this Span<T> span, RefEnumerable<T> destination)
276275
{
277276
return destination.TryCopyFrom(span);
278277
}
279-
280-
/// <summary>
281-
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the given reference is out of range.
282-
/// </summary>
283-
internal static void ThrowArgumentOutOfRangeExceptionForInvalidReference()
284-
{
285-
throw new ArgumentOutOfRangeException("value", "The input reference does not belong to an element of the input span");
286-
}
287278
}

tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlySpanExtensions.cs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,17 @@ public void Test_ReadOnlySpanExtensions_IndexOf_Empty()
9898
{
9999
static void Test<T>()
100100
{
101-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
102-
{
103-
T? a = default;
101+
T? a = default;
104102

105-
_ = default(ReadOnlySpan<T?>).IndexOf(in a);
106-
});
103+
int indexOfA = default(ReadOnlySpan<T?>).IndexOf(in a);
107104

108-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
109-
{
110-
ReadOnlySpan<T?> data = new T?[] { default };
105+
Assert.AreEqual(-1, indexOfA);
111106

112-
_ = data.Slice(1).IndexOf(in data[0]);
113-
});
107+
ReadOnlySpan<T?> data = new T?[] { default };
108+
109+
int indexOfData = data.Slice(1).IndexOf(in data[0]);
110+
111+
Assert.AreEqual(-1, indexOfData);
114112
}
115113

116114
Test<byte>();
@@ -148,29 +146,27 @@ public void Test_ReadOnlySpanExtensions_IndexOf_NotEmpty_OutOfRange()
148146
static void Test<T>()
149147
{
150148
// Before start
151-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
152-
{
153-
ReadOnlySpan<T?> data = new T?[] { default, default, default, default };
149+
ReadOnlySpan<T?> data = new T?[] { default, default, default, default };
150+
151+
int index = data.Slice(1).IndexOf(in data[0]);
154152

155-
_ = data.Slice(1).IndexOf(in data[0]);
156-
});
153+
Assert.AreEqual(-1, index);
157154

158155
// After end
159-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
160-
{
161-
ReadOnlySpan<T?> data = new T?[] { default, default, default, default };
156+
data = new T?[] { default, default, default, default };
162157

163-
_ = data.Slice(0, 2).IndexOf(in data[2]);
164-
});
158+
index = data.Slice(0, 2).IndexOf(in data[2]);
159+
160+
Assert.AreEqual(-1, index);
165161

166162
// Local variable
167-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
168-
{
169-
T?[]? dummy = new T?[] { default };
170-
ReadOnlySpan<T?> data = new T?[] { default, default, default, default };
163+
T?[]? dummy = new T?[] { default };
164+
165+
data = new T?[] { default, default, default, default };
166+
167+
index = data.IndexOf(in dummy[0]);
171168

172-
_ = data.IndexOf(in dummy[0]);
173-
});
169+
Assert.AreEqual(-1, index);
174170
}
175171

176172
Test<byte>();

tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpanExtensions.cs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,17 @@ public void Test_SpanExtensions_IndexOf_Empty()
5151
{
5252
static void Test<T>()
5353
{
54-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
55-
{
56-
T? a = default;
54+
T? a = default;
5755

58-
_ = default(Span<T?>).IndexOf(ref a);
59-
});
56+
int indexOfA = default(Span<T?>).IndexOf(ref a);
6057

61-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
62-
{
63-
Span<T?> data = new T?[] { default };
58+
Assert.AreEqual(-1, indexOfA);
6459

65-
_ = data.Slice(1).IndexOf(ref data[0]);
66-
});
60+
Span<T?> data = new T?[] { default };
61+
62+
int indexOfData = data.Slice(1).IndexOf(ref data[0]);
63+
64+
Assert.AreEqual(-1, indexOfData);
6765
}
6866

6967
Test<byte>();
@@ -101,29 +99,27 @@ public void Test_SpanExtensions_IndexOf_NotEmpty_OutOfRange()
10199
static void Test<T>()
102100
{
103101
// Before start
104-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
105-
{
106-
Span<T?> data = new T?[] { default, default, default, default };
102+
Span<T?> data = new T?[] { default, default, default, default };
103+
104+
int index = data.Slice(1).IndexOf(ref data[0]);
107105

108-
_ = data.Slice(1).IndexOf(ref data[0]);
109-
});
106+
Assert.AreEqual(-1, index);
110107

111108
// After end
112-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
113-
{
114-
Span<T?> data = new T?[] { default, default, default, default };
109+
data = new T?[] { default, default, default, default };
115110

116-
_ = data.Slice(0, 2).IndexOf(ref data[2]);
117-
});
111+
index = data.Slice(0, 2).IndexOf(ref data[2]);
112+
113+
Assert.AreEqual(-1, index);
118114

119115
// Local variable
120-
_ = Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
121-
{
122-
T?[]? dummy = new T?[] { default };
123-
Span<T?> data = new T?[] { default, default, default, default };
116+
T?[]? dummy = new T?[] { default };
117+
118+
data = new T?[] { default, default, default, default };
119+
120+
index = data.IndexOf(ref dummy[0]);
124121

125-
_ = data.IndexOf(ref dummy[0]);
126-
});
122+
Assert.AreEqual(-1, index);
127123
}
128124

129125
Test<byte>();

0 commit comments

Comments
 (0)