Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit e78caf8

Browse files
bbartelsstephentoub
authored andcommitted
Fixed missing Dispose call on Union on empty enumerable (#40384)
1 parent 70d2b62 commit e78caf8

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

src/System.Linq/src/System/Linq/Union.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ public sealed override bool MoveNext()
9999
for (IEnumerable<TSource> enumerable = GetEnumerable(0); enumerable != null; enumerable = GetEnumerable(_state - 1))
100100
{
101101
IEnumerator<TSource> enumerator = enumerable.GetEnumerator();
102+
SetEnumerator(enumerator);
103+
102104
++_state;
103105
if (enumerator.MoveNext())
104106
{
105-
SetEnumerator(enumerator);
106107
StoreFirst();
107108
return true;
108109
}

src/System.Linq/tests/EnumerableTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,5 +345,25 @@ public DelegateIterator(
345345

346346
void IDisposable.Dispose() => _dispose();
347347
}
348+
349+
protected sealed class DisposeTrackingEnumerable<T> : IEnumerable<T>
350+
{
351+
public bool EnumeratorDisposed { get; private set; }
352+
353+
354+
public IEnumerator<T> GetEnumerator() => new Enumerator(this);
355+
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this);
356+
357+
private sealed class Enumerator : IEnumerator<T>
358+
{
359+
private readonly DisposeTrackingEnumerable<T> _enumerable;
360+
public Enumerator(DisposeTrackingEnumerable<T> enumerable) => _enumerable = enumerable;
361+
public void Dispose() => _enumerable.EnumeratorDisposed = true;
362+
public T Current => default;
363+
object IEnumerator.Current => default;
364+
public bool MoveNext() => false;
365+
public void Reset() { }
366+
}
367+
}
348368
}
349369
}

src/System.Linq/tests/UnionTests.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Collections.Generic;
7+
using System.Collections;
78
using Xunit;
89

910
namespace System.Linq.Tests
@@ -413,5 +414,19 @@ public void HashSetWithBuiltInComparer_HashSetContainsNotUsed()
413414
Assert.Equal(new[] { "A", "a" }, input2.Union(input1, EqualityComparer<string>.Default));
414415
Assert.Equal(new[] { "A" }, input2.Union(input1, StringComparer.OrdinalIgnoreCase));
415416
}
417+
418+
[Fact]
419+
public void UnionFollowedBySelectOnEmptyEnumerableInvokesDispose()
420+
{
421+
var enum1 = new DisposeTrackingEnumerable<int>();
422+
var enum2 = new DisposeTrackingEnumerable<int>();
423+
Assert.False(enum1.EnumeratorDisposed);
424+
Assert.False(enum2.EnumeratorDisposed);
425+
426+
foreach (int value in enum1.Union(enum2)) { }
427+
428+
Assert.True(enum1.EnumeratorDisposed);
429+
Assert.True(enum2.EnumeratorDisposed);
430+
}
416431
}
417432
}

0 commit comments

Comments
 (0)