Skip to content

Commit 771c640

Browse files
andrewjsaidpull[bot]
authored andcommitted
Fix LINQ Last() in ConcatNIterator to also check base case (Concat2Iterator) (#108486)
* Fix LINQ Last() in ConcatNIterator to also check base case (Concat2Iterator) * Add a few more test cases of empty concats * Simplify solution as suggested in PR Review
1 parent 17f1c48 commit 771c640

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/libraries/System.Linq/src/System/Linq/Concat.SpeedOpt.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,21 @@ private TSource[] PreallocatingToArray()
326326

327327
public override TSource? TryGetLast(out bool found)
328328
{
329-
ConcatNIterator<TSource>? node = this;
329+
ConcatNIterator<TSource>? node, previousN = this;
330+
TSource? result;
330331
do
331332
{
332-
TSource? result = node._head.TryGetLast(out found);
333+
node = previousN;
334+
result = node._head.TryGetLast(out found);
333335
if (found)
334336
{
335337
return result;
336338
}
337339
}
338-
while ((node = node!.PreviousN) is not null);
340+
while ((previousN = node.PreviousN) is not null);
339341

340-
found = false;
341-
return default;
342+
Debug.Assert(node._tail is Concat2Iterator<TSource>);
343+
return node._tail.TryGetLast(out found);
342344
}
343345
}
344346

src/libraries/System.Linq/tests/ConcatTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public void VerifyEquals(IEnumerable<int> expected, IEnumerable<int> actual)
9393
[MemberData(nameof(ConcatWithSelfData))]
9494
[MemberData(nameof(ChainedCollectionConcatData))]
9595
[MemberData(nameof(AppendedPrependedConcatAlternationsData))]
96+
[MemberData(nameof(ConcatWithEmptyEnumerableData))]
9697
public void First_Last_ElementAt(IEnumerable<int> _, IEnumerable<int> actual)
9798
{
9899
int count = actual.Count();
@@ -232,6 +233,32 @@ public static IEnumerable<object[]> AppendedPrependedConcatAlternationsData()
232233
}
233234
}
234235

236+
public static IEnumerable<object[]> ConcatWithEmptyEnumerableData()
237+
{
238+
List<int> baseList = [0, 1, 2, 3, 4];
239+
240+
yield return new object[]
241+
{
242+
Enumerable.Range(0, 5),
243+
Enumerable.Concat(Enumerable.Concat(new List<int>(), new List<int>()), baseList)
244+
};
245+
yield return new object[]
246+
{
247+
Enumerable.Range(0, 5),
248+
Enumerable.Concat(new List<int>(), baseList)
249+
};
250+
yield return new object[]
251+
{
252+
Enumerable.Range(0, 5),
253+
Enumerable.Concat(Enumerable.Concat(baseList, new List<int>()), new List<int>())
254+
};
255+
yield return new object[]
256+
{
257+
Enumerable.Range(0, 5),
258+
Enumerable.Concat(baseList, new List<int>())
259+
};
260+
}
261+
235262
private static IEnumerable<object[]> GenerateSourcesData(
236263
Func<IEnumerable<int>, IEnumerable<int>> outerTransform = null,
237264
Func<IEnumerable<int>, IEnumerable<int>> innerTransform = null)

0 commit comments

Comments
 (0)