Skip to content

Commit 6d23974

Browse files
authored
Merge pull request Cysharp#173 from prozolic/FromImmutableHashSet
Add ImmutableHashSet.AsValueEnumerable
2 parents e77e940 + 039c3ef commit 6d23974

3 files changed

Lines changed: 96 additions & 0 deletions

File tree

src/ZLinq/Linq/AsValueEnumerable.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ public static ValueEnumerable<FromSortedSet<T>, T> AsValueEnumerable<T>(this Sor
9595
public static ValueEnumerable<FromImmutableArray<T>, T> AsValueEnumerable<T>(this ImmutableArray<T> source)
9696
{
9797
return new(new(source));
98+
}
99+
100+
public static ValueEnumerable<FromImmutableHashSet<T>, T> AsValueEnumerable<T>(this ImmutableHashSet<T> source)
101+
{
102+
return new(new(Throws.IfNull(source)));
98103
}
99104

100105
#endif
@@ -1073,10 +1078,60 @@ public bool TryGetNext(out T current)
10731078
public void Dispose()
10741079
{
10751080
}
1081+
}
1082+
1083+
[StructLayout(LayoutKind.Auto)]
1084+
public struct FromImmutableHashSet<T>(ImmutableHashSet<T> source) : IValueEnumerator<T>
1085+
{
1086+
bool isInit;
1087+
ImmutableHashSet<T>.Enumerator enumerator;
1088+
1089+
internal ImmutableHashSet<T> GetSource() => source;
1090+
1091+
public bool TryGetNonEnumeratedCount(out int count)
1092+
{
1093+
count = source.Count;
1094+
return true;
1095+
}
1096+
1097+
public bool TryGetSpan(out ReadOnlySpan<T> span)
1098+
{
1099+
span = default;
1100+
return false;
1101+
}
1102+
1103+
public bool TryCopyTo(Span<T> destination, Index offset) => false;
1104+
1105+
public bool TryGetNext(out T current)
1106+
{
1107+
if (!isInit)
1108+
{
1109+
isInit = true;
1110+
enumerator = source.GetEnumerator();
1111+
}
1112+
1113+
if (enumerator.MoveNext())
1114+
{
1115+
current = enumerator.Current;
1116+
return true;
1117+
}
1118+
1119+
Unsafe.SkipInit(out current);
1120+
return false;
1121+
}
1122+
1123+
public void Dispose()
1124+
{
1125+
if (isInit)
1126+
{
1127+
enumerator.Dispose();
1128+
}
1129+
}
10761130
}
10771131

10781132
#endif
10791133

1134+
10801135
#if NET9_0_OR_GREATER
10811136

10821137
[StructLayout(LayoutKind.Auto)]

src/ZLinq/Linq/Contains.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,19 @@ public static Boolean Contains<TSource>(this ValueEnumerable<FromHashSet<TSource
3030
}
3131

3232
public static Boolean Contains<TSource>(this ValueEnumerable<FromSortedSet<TSource>, TSource> source, TSource value)
33+
{
34+
var innerCollection = source.Enumerator.GetSource();
35+
return innerCollection.Contains(value);
36+
}
37+
38+
#if NET8_0_OR_GREATER
39+
40+
public static Boolean Contains<TSource>(this ValueEnumerable<FromImmutableHashSet<TSource>, TSource> source, TSource value)
3341
{
3442
var innerCollection = source.Enumerator.GetSource();
3543
return innerCollection.Contains(value);
3644
}
45+
#endif
3746

3847
public static Boolean Contains<TEnumerator, TSource>(this ValueEnumerable<TEnumerator, TSource> source, TSource value)
3948
where TEnumerator : struct, IValueEnumerator<TSource>

tests/ZLinq.Tests/Linq/AsValueEnumerableTest.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,39 @@ public void FromImmutableArray_BasicFunctionality()
380380

381381
var resultArray = result.ToArray();
382382
resultArray.ShouldBe(source.ToArray());
383+
}
384+
385+
[Fact]
386+
public void FromImmutableHashSet_BasicFunctionality()
387+
{
388+
// Arrange
389+
var source = ImmutableHashSet.Create(5, 2, 1, 4, 3);
390+
391+
// Act
392+
var result = source.AsValueEnumerable();
393+
394+
// Assert
395+
result.TryGetNonEnumeratedCount(out var count).ShouldBeTrue();
396+
count.ShouldBe(source.Count);
397+
398+
result.TryGetSpan(out var span).ShouldBeFalse();
399+
400+
var resultArray = result.ToArray();
401+
resultArray.ShouldBe(new[] { 1, 2, 3, 4, 5 }); // SortedSet should be ordered
383402
}
403+
404+
[Fact]
405+
public void FromImmutableHashSet_ContainsOptimization()
406+
{
407+
// Arrange
408+
var source = ImmutableHashSet.Create(5, 2, 1, 4, 3);
409+
var result = source.AsValueEnumerable();
410+
411+
// Act & Assert
412+
result.Contains(3).ShouldBeTrue();
413+
result.Contains(6).ShouldBeFalse();
414+
}
415+
384416
#endif
385417

386418
#if NET9_0_OR_GREATER

0 commit comments

Comments
 (0)