Skip to content

Commit a2941fc

Browse files
committed
[Contains] Implement Visitor concept.
1 parent fb614e2 commit a2941fc

12 files changed

+551
-161
lines changed

Documents/BenchmarksResults/Contains.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical
1414

1515

1616
```
17-
| Method | Mean | Error | StdDev | Ratio | RatioSD | Code Size | Gen 0 | Gen 1 | Gen 2 | Allocated |
18-
|-------------------- |---------:|----------:|----------:|------:|--------:|----------:|-------:|------:|------:|----------:|
19-
| Array | 1.135 μs | 0.0180 μs | 0.0169 μs | 1.00 | 0.00 | 98 B | - | - | - | - |
20-
| StructLinq | 1.908 μs | 0.0091 μs | 0.0086 μs | 1.68 | 0.02 | 156 B | 0.0038 | - | - | 32 B |
21-
| StructLinqZeroAlloc | 2.513 μs | 0.0077 μs | 0.0072 μs | 2.21 | 0.03 | 236 B | - | - | - | - |
17+
| Method | Mean | Error | StdDev | Ratio | Code Size | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|-------------------- |---------:|----------:|----------:|------:|----------:|-------:|------:|------:|----------:|
19+
| Array | 1.128 μs | 0.0031 μs | 0.0026 μs | 1.00 | 98 B | - | - | - | - |
20+
| StructLinq | 2.592 μs | 0.0129 μs | 0.0114 μs | 2.30 | 176 B | 0.0038 | - | - | 32 B |
21+
| StructLinqZeroAlloc | 3.803 μs | 0.0059 μs | 0.0053 μs | 3.37 | 256 B | - | - | - | - |

Documents/BenchmarksResults/ContainsOnBigStruct.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical
1414

1515

1616
```
17-
| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
18-
|----------------------------------------- |----------:|----------:|----------:|------:|--------:|------:|------:|------:|----------:|
19-
| Linq | 5.342 μs | 0.0205 μs | 0.0192 μs | 1.00 | 0.00 | - | - | - | - |
20-
| Array | 4.678 μs | 0.0246 μs | 0.0230 μs | 0.88 | 0.00 | - | - | - | - |
21-
| StructLinq | 23.504 μs | 0.1103 μs | 0.0977 μs | 4.40 | 0.02 | - | - | - | - |
22-
| RefStructLinq | 17.033 μs | 0.0842 μs | 0.0787 μs | 3.19 | 0.02 | - | - | - | - |
23-
| StructLinqWithCustomComparer | 14.999 μs | 0.0528 μs | 0.0468 μs | 2.81 | 0.01 | - | - | - | - |
24-
| RefStructLinqZeroAllocwithCustomComparer | 5.025 μs | 0.0157 μs | 0.0147 μs | 0.94 | 0.00 | - | - | - | - |
17+
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|----------------------------------------- |----------:|----------:|----------:|------:|------:|------:|------:|----------:|
19+
| Linq | 6.379 μs | 0.0133 μs | 0.0117 μs | 1.00 | - | - | - | - |
20+
| Array | 6.350 μs | 0.0166 μs | 0.0147 μs | 1.00 | - | - | - | - |
21+
| StructLinq | 22.289 μs | 0.0510 μs | 0.0398 μs | 3.49 | - | - | - | - |
22+
| RefStructLinq | 16.671 μs | 0.0332 μs | 0.0311 μs | 2.61 | - | - | - | - |
23+
| StructLinqWithCustomComparer | 15.165 μs | 0.0679 μs | 0.0602 μs | 2.38 | - | - | - | - |
24+
| RefStructLinqZeroAllocwithCustomComparer | 5.093 μs | 0.0144 μs | 0.0120 μs | 0.80 | - | - | - | - |

Documents/BenchmarksResults/ContainsWhere.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical
1414

1515

1616
```
17-
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | Code Size |
18-
|-------------------- |---------:|---------:|---------:|------:|------:|------:|------:|----------:|----------:|
19-
| Linq | 31.42 μs | 0.110 μs | 0.098 μs | 1.00 | - | - | - | 48 B | 1257 B |
20-
| Array | 31.45 μs | 0.107 μs | 0.095 μs | 1.00 | - | - | - | 48 B | 1257 B |
21-
| StructLinq | 14.98 μs | 0.136 μs | 0.114 μs | 0.48 | - | - | - | 64 B | 401 B |
22-
| StructLinqZeroAlloc | 13.78 μs | 0.041 μs | 0.035 μs | 0.44 | - | - | - | - | 771 B |
17+
| Method | Mean | Error | StdDev | Ratio | Code Size | Gen 0 | Gen 1 | Gen 2 | Allocated |
18+
|-------------------- |---------:|---------:|---------:|------:|----------:|------:|------:|------:|----------:|
19+
| Linq | 31.71 μs | 0.122 μs | 0.095 μs | 1.00 | 1257 B | - | - | - | 48 B |
20+
| Array | 30.42 μs | 0.065 μs | 0.054 μs | 0.96 | 1257 B | - | - | - | 48 B |
21+
| StructLinq | 11.24 μs | 0.051 μs | 0.045 μs | 0.35 | 302 B | - | - | - | 64 B |
22+
| StructLinqZeroAlloc | 10.39 μs | 0.071 μs | 0.063 μs | 0.33 | 716 B | - | - | - | - |

Documents/BenchmarksResults/ContainsWhereOnBigStruct.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ Intel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical
1616
```
1717
| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |
1818
|----------------------------------------- |---------:|---------:|---------:|------:|------:|------:|------:|----------:|
19-
| Linq | 52.22 μs | 0.204 μs | 0.181 μs | 1.00 | - | - | - | 80 B |
20-
| Array | 49.59 μs | 0.290 μs | 0.271 μs | 0.95 | - | - | - | 80 B |
21-
| StructLinq | 39.00 μs | 0.216 μs | 0.191 μs | 0.75 | - | - | - | - |
22-
| RefStructLinq | 28.34 μs | 0.126 μs | 0.118 μs | 0.54 | - | - | - | - |
23-
| StructLinqWithCustomComparer | 31.46 μs | 0.120 μs | 0.107 μs | 0.60 | - | - | - | - |
24-
| RefStructLinqZeroAllocwithCustomComparer | 15.58 μs | 0.137 μs | 0.128 μs | 0.30 | - | - | - | - |
19+
| Linq | 49.68 μs | 0.315 μs | 0.294 μs | 1.00 | - | - | - | 80 B |
20+
| Array | 52.62 μs | 0.214 μs | 0.190 μs | 1.06 | - | - | - | 80 B |
21+
| StructLinq | 52.99 μs | 0.331 μs | 0.310 μs | 1.07 | - | - | - | - |
22+
| RefStructLinq | 30.43 μs | 0.039 μs | 0.030 μs | 0.61 | - | - | - | - |
23+
| StructLinqWithCustomComparer | 22.06 μs | 0.198 μs | 0.165 μs | 0.44 | - | - | - | - |
24+
| RefStructLinqZeroAllocwithCustomComparer | 18.84 μs | 0.052 μs | 0.046 μs | 0.38 | - | - | - | - |
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using FluentAssertions;
2+
using Xunit;
3+
4+
namespace StructLinq.Tests
5+
{
6+
public class ContainsStringTests
7+
{
8+
[Fact]
9+
public void ShouldReturnTrue()
10+
{
11+
var enumerable = StructEnumerable.Range(0, 100).Select(x=> x.ToString());
12+
for (int i = 0; i < 100; i++)
13+
{
14+
enumerable.Contains(i.ToString(), x => x).Should().BeTrue();
15+
}
16+
}
17+
18+
[Fact]
19+
public void ShouldReturnFalse()
20+
{
21+
var enumerable = StructEnumerable.Range(0, 100).Select(x=> x.ToString());
22+
enumerable.Contains((-10).ToString(), x => x).Should().BeFalse();
23+
}
24+
25+
[Fact]
26+
public void ShouldReturnFalseWithInterface()
27+
{
28+
var enumerable = StructEnumerable.Range(0, 100).Select(x=> x.ToString());
29+
enumerable.Contains((-10).ToString()).Should().BeFalse();
30+
}
31+
32+
[Fact]
33+
public void ShouldReturnTrueWithInterface()
34+
{
35+
var enumerable = StructEnumerable.Range(0, 100).Select(x=> x.ToString());
36+
for (int i = 0; i < 100; i++)
37+
{
38+
enumerable.Contains(i.ToString()).Should().BeTrue();
39+
}
40+
}
41+
}
42+
}

src/StructLinq.Tests/ContainsTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using FluentAssertions;
2+
using StructLinq.Range;
23
using Xunit;
34

45
namespace StructLinq.Tests
@@ -15,13 +16,30 @@ public void ShouldReturnTrue()
1516
}
1617
}
1718

19+
[Fact]
20+
public void ShouldReturnTrueWithVisitor()
21+
{
22+
var enumerable = StructEnumerable.Range(0, 100);
23+
for (int i = 0; i < 100; i++)
24+
{
25+
enumerable.Contains(i, x => (IStructEnumerable<int, RangeEnumerator>)x).Should().BeTrue();
26+
}
27+
}
28+
1829
[Fact]
1930
public void ShouldReturnFalse()
2031
{
2132
var enumerable = StructEnumerable.Range(0, 100);
2233
enumerable.Contains(-10, x => x).Should().BeFalse();
2334
}
2435

36+
[Fact]
37+
public void ShouldReturnFalseWithVisitor()
38+
{
39+
var enumerable = StructEnumerable.Range(0, 100);
40+
enumerable.Contains(-10, x => (IStructEnumerable<int, RangeEnumerator>)x).Should().BeFalse();
41+
}
42+
2543
[Fact]
2644
public void ShouldReturnFalseWithInterface()
2745
{
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Collections.Generic;
2+
using System.Runtime.CompilerServices;
3+
4+
namespace StructLinq.Contains
5+
{
6+
readonly struct ContainsVisitor<T, TComparer> : IVisitor<T>
7+
where TComparer : IEqualityComparer<T>
8+
{
9+
private readonly TComparer comparer;
10+
private readonly T x;
11+
public ContainsVisitor(TComparer comparer, T x)
12+
{
13+
this.comparer = comparer;
14+
this.x = x;
15+
}
16+
17+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
18+
public bool Visit(T input)
19+
{
20+
return !comparer.Equals(x, input);
21+
}
22+
}
23+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
4+
5+
// ReSharper disable once CheckNamespace
6+
namespace StructLinq
7+
{
8+
public static partial class StructEnumerable
9+
{
10+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11+
private static bool RefInnerContains<T, TEnumerator, TComparer>(TEnumerator enumerator, T x, TComparer comparer)
12+
where TEnumerator : struct, IRefStructEnumerator<T>
13+
where TComparer : IInEqualityComparer<T>
14+
{
15+
while (enumerator.MoveNext())
16+
{
17+
ref var enumeratorCurrent = ref enumerator.Current;
18+
if (comparer.Equals(in x, in enumeratorCurrent))
19+
return true;
20+
}
21+
enumerator.Dispose();
22+
return false;
23+
}
24+
25+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
26+
public static bool Contains<T, TEnumerable, TEnumerator, TComparer>(this TEnumerable enumerable, T x, TComparer comparer, Func<TEnumerable, IRefStructEnumerable<T, TEnumerator>> _)
27+
where TEnumerator : struct, IRefStructEnumerator<T>
28+
where TEnumerable : IRefStructEnumerable<T, TEnumerator>
29+
where TComparer : IInEqualityComparer<T>
30+
{
31+
var enumerator = enumerable.GetEnumerator();
32+
return RefInnerContains(enumerator, x, comparer);
33+
}
34+
35+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
36+
public static bool Contains<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, T x, Func<TEnumerable, IRefStructEnumerable<T, TEnumerator>> _)
37+
where TEnumerator : struct, IRefStructEnumerator<T>
38+
where TEnumerable : IRefStructEnumerable<T, TEnumerator>
39+
{
40+
var enumerator = enumerable.GetEnumerator();
41+
var equalityComparer = InEqualityComparer<T>.Default;
42+
return RefInnerContains(enumerator, x, equalityComparer);
43+
}
44+
45+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
46+
public static bool Contains<T, TEnumerator, TComparer>(this IRefStructEnumerable<T, TEnumerator> enumerable, T x, TComparer comparer)
47+
where TEnumerator : struct, IRefStructEnumerator<T>
48+
where TComparer : IInEqualityComparer<T>
49+
{
50+
var enumerator = enumerable.GetEnumerator();
51+
return RefInnerContains(enumerator, x, comparer);
52+
}
53+
54+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
55+
public static bool Contains<T, TEnumerator>(this IRefStructEnumerable<T, TEnumerator> enumerable, T x)
56+
where TEnumerator : struct, IRefStructEnumerator<T>
57+
{
58+
var enumerator = enumerable.GetEnumerator();
59+
var equalityComparer = InEqualityComparer<T>.Default;
60+
return RefInnerContains(enumerator, x, equalityComparer);
61+
}
62+
}
63+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
4+
5+
// ReSharper disable once CheckNamespace
6+
namespace StructLinq
7+
{
8+
public static partial class StructEnumerable
9+
{
10+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11+
private static bool InnerCollectionContains<T, TEnumerator, TComparer>(TEnumerator enumerator, T x, TComparer comparer)
12+
where TEnumerator : struct, ICollectionEnumerator<T>
13+
where TComparer : IEqualityComparer<T>
14+
{
15+
var count = enumerator.Count;
16+
for (int i = 0; i < count; i++)
17+
{
18+
var current = enumerator.Get(i);
19+
if (comparer.Equals(x, current))
20+
{
21+
enumerator.Dispose();
22+
return true;
23+
}
24+
}
25+
enumerator.Dispose();
26+
return false;
27+
}
28+
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public static bool Contains<T, TEnumerable, TEnumerator, TComparer>(this TEnumerable enumerable, T x, TComparer comparer, Func<TEnumerable, IStructCollection<T, TEnumerator>> _)
31+
where TEnumerator : struct, ICollectionEnumerator<T>
32+
where TEnumerable : IStructCollection<T, TEnumerator>
33+
where TComparer : IEqualityComparer<T>
34+
{
35+
var enumerator = enumerable.GetEnumerator();
36+
return InnerCollectionContains(enumerator, x, comparer);
37+
}
38+
39+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
40+
public static bool Contains<T, TEnumerable, TEnumerator>(this TEnumerable enumerable, T x, Func<TEnumerable, IStructCollection<T, TEnumerator>> _)
41+
where TEnumerator : struct, ICollectionEnumerator<T>
42+
where TEnumerable : IStructCollection<T, TEnumerator>
43+
{
44+
var enumerator = enumerable.GetEnumerator();
45+
var equalityComparer = EqualityComparer<T>.Default;
46+
return InnerCollectionContains(enumerator, x, equalityComparer);
47+
}
48+
49+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
50+
public static bool Contains<T, TEnumerator, TComparer>(this IStructCollection<T, TEnumerator> enumerable, T x, TComparer comparer)
51+
where TEnumerator : struct, ICollectionEnumerator<T>
52+
where TComparer : IEqualityComparer<T>
53+
{
54+
var enumerator = enumerable.GetEnumerator();
55+
return InnerCollectionContains(enumerator, x, comparer);
56+
}
57+
58+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
59+
public static bool Contains<T, TEnumerator>(this IStructCollection<T, TEnumerator> enumerable, T x)
60+
where TEnumerator : struct, ICollectionEnumerator<T>
61+
{
62+
var enumerator = enumerable.GetEnumerator();
63+
var equalityComparer = EqualityComparer<T>.Default;
64+
return InnerCollectionContains(enumerator, x, equalityComparer);
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)