Skip to content

Commit 8500481

Browse files
committed
Replace casts by generics constraints
1 parent d6bb02c commit 8500481

21 files changed

+429
-203
lines changed

NetFabric.Hyperlinq.SourceGenerator.UnitTests/GenerateSourceTests.cs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,34 @@ public class GenerateSourceTests
1313
public static TheoryData<string[], string> GeneratorSources
1414
=> new()
1515
{
16+
//{
17+
// new[] { "TestData/Source/AsValueEnumerable.Empty.cs" },
18+
// "TestData/Results/Empty.cs"
19+
//},
20+
//{
21+
// new[] { "TestData/Source/AsValueEnumerable.Empty2.cs" },
22+
// "TestData/Results/Empty.cs"
23+
//},
24+
//{
25+
// new[] { "TestData/Source/AsValueEnumerable.Repeat.cs" },
26+
// "TestData/Results/AsValueEnumerable.Repeat.cs"
27+
//},
28+
1629
{
17-
new[] { "TestData/Source/AsValueEnumerable.Empty.cs" },
18-
"TestData/Results/Empty.cs"
19-
},
20-
{
21-
new[] { "TestData/Source/AsValueEnumerable.Empty2.cs" },
22-
"TestData/Results/Empty.cs"
30+
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs" },
31+
"TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs"
2332
},
2433
{
25-
new[] { "TestData/Source/AsValueEnumerable.Repeat.cs" },
26-
"TestData/Results/AsValueEnumerable.Repeat.cs"
34+
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs" },
35+
"TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs"
2736
},
2837
{
2938
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs" },
3039
"TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs"
3140
},
3241
{
33-
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs" },
34-
"TestData/Results/AsValueEnumerable.TestEnumerableWithValueTypeEnumerator.cs"
35-
},
36-
{
37-
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs" },
38-
"TestData/Results/AsValueEnumerable.TestEnumerableWithReferenceTypeEnumerator.cs"
42+
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs" },
43+
"TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfacesButEnumeratorWithResetAndDispose.cs"
3944
},
4045
{
4146
new[] { "TestData/Source/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs" },
@@ -53,6 +58,10 @@ public static TheoryData<string[], string> GeneratorSources
5358
new[] { "TestData/Source/AsValueEnumerable.TestList.cs" },
5459
"TestData/Results/AsValueEnumerable.TestList.cs"
5560
},
61+
{
62+
new[] { "TestData/Source/AsValueEnumerable.IReadOnlyList.cs" },
63+
"TestData/Results/AsValueEnumerable.IReadOnlyList.cs"
64+
},
5665
{
5766
new[] { "TestData/Source/AsValueEnumerable.TestListWithExplicitInterfaces.cs" },
5867
"TestData/Results/AsValueEnumerable.TestListWithExplicitInterfaces.cs"
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#nullable enable
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
using System.Runtime.CompilerServices;
7+
8+
namespace NetFabric.Hyperlinq
9+
{
10+
static partial class GeneratedExtensionMethods
11+
{
12+
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
public static AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_<System.Collections.Generic.IReadOnlyList<TestValueType>> AsValueEnumerable(this System.Collections.Generic.IReadOnlyList<TestValueType> source)
15+
=> new(source, source);
16+
17+
public readonly struct AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_<TEnumerable>
18+
: IValueReadOnlyList<TestValueType, ValueEnumerator<TestValueType>>, IList<TestValueType>
19+
where TEnumerable : IReadOnlyList<TestValueType>
20+
{
21+
readonly System.Collections.Generic.IReadOnlyList<TestValueType> source;
22+
readonly TEnumerable source2;
23+
24+
internal AsValueEnumerable_System_Collections_Generic_IReadOnlyList_TestValueType_(System.Collections.Generic.IReadOnlyList<TestValueType> source, TEnumerable source2)
25+
=> (this.source, this.source2) = (source, source2);
26+
27+
// Implement IValueEnumerable<TestValueType, ValueEnumerator<TestValueType>>
28+
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public ValueEnumerator<TestValueType> GetEnumerator() => new(source2.GetEnumerator());
31+
32+
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => source2.GetEnumerator();
33+
34+
IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator();
35+
36+
// Implement ICollection<TestValueType>
37+
38+
public int Count => source2.Count;
39+
40+
public bool IsReadOnly => true;
41+
42+
void ICollection<TestValueType>.Add(TestValueType item) => throw new NotSupportedException();
43+
44+
bool ICollection<TestValueType>.Remove(TestValueType item) => throw new NotSupportedException();
45+
46+
void ICollection<TestValueType>.Clear() => throw new NotSupportedException();
47+
48+
public void CopyTo(Span<TestValueType> span)
49+
{
50+
if (Count is 0) return;
51+
if (span.Length < Count) throw new ArgumentException("Destination span was not long enough.", nameof(span));
52+
53+
var index = 0;
54+
foreach (var current in this)
55+
{
56+
span[index] = current;
57+
checked { index++; }
58+
}
59+
}
60+
61+
public bool Contains(TestValueType item)
62+
{
63+
foreach (var current in this)
64+
{
65+
if (EqualityComparer<TestValueType>.Default.Equals(current, item)) return true;
66+
}
67+
return true;
68+
}
69+
70+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
71+
public void CopyTo(TestValueType[] array, int arrayIndex) => CopyTo(array.AsSpan(arrayIndex));
72+
73+
// Implement IList<TestValueType>
74+
75+
public TestValueType this[int index] => source2[index];
76+
77+
TestValueType IList<TestValueType>.this[int index]
78+
{
79+
get => source2[index];
80+
set => throw new NotSupportedException();
81+
}
82+
83+
void IList<TestValueType>.Insert(int index, TestValueType item) => throw new NotSupportedException();
84+
85+
void IList<TestValueType>.RemoveAt(int index) => throw new NotSupportedException();
86+
87+
public int IndexOf(TestValueType item)
88+
{
89+
if (Count is not 0)
90+
{
91+
var index = 0;
92+
foreach (var current in this)
93+
{
94+
if (EqualityComparer<TestValueType>.Default.Equals(current, item)) return index;
95+
96+
checked { index++; }
97+
}
98+
}
99+
return -1;
100+
}
101+
}
102+
}
103+
}

NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/AsValueEnumerable.Repeat.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ static partial class GeneratedExtensionMethods
1111
{
1212

1313
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
public static NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable<int> AsValueEnumerable(this NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable<int> source) => source;
14+
public static NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable<int> AsValueEnumerable(this NetFabric.Hyperlinq.ValueEnumerable.RepeatEnumerable<int> source)
15+
=> source;
1516
}
1617
}

NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/AsValueEnumerable.TestCollection.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,31 @@ static partial class GeneratedExtensionMethods
1111
{
1212

1313
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
public static AsValueEnumerable_TestCollection_TestValueType_ AsValueEnumerable(this TestCollection<TestValueType> source) => new(source);
14+
public static AsValueEnumerable_TestCollection_TestValueType_<TestCollection<TestValueType>> AsValueEnumerable(this TestCollection<TestValueType> source)
15+
=> new(source, source);
1516

16-
public readonly struct AsValueEnumerable_TestCollection_TestValueType_: IValueReadOnlyCollection<TestValueType, TestCollection<TestValueType>.Enumerator>, ICollection<TestValueType>
17+
public readonly struct AsValueEnumerable_TestCollection_TestValueType_<TEnumerable>
18+
: IValueReadOnlyCollection<TestValueType, TestCollection<TestValueType>.Enumerator>, ICollection<TestValueType>
19+
where TEnumerable : ICollection<TestValueType>
1720
{
1821
readonly TestCollection<TestValueType> source;
22+
readonly TEnumerable source2;
1923

20-
internal AsValueEnumerable_TestCollection_TestValueType_(TestCollection<TestValueType> source) => this.source = source;
24+
internal AsValueEnumerable_TestCollection_TestValueType_(TestCollection<TestValueType> source, TEnumerable source2)
25+
=> (this.source, this.source2) = (source, source2);
2126

2227
// Implement IValueEnumerable<TestValueType, TestCollection<TestValueType>.Enumerator>
2328

2429
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2530
public TestCollection<TestValueType>.Enumerator GetEnumerator() => source.GetEnumerator();
2631

27-
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => source.GetEnumerator();
32+
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => source2.GetEnumerator();
2833

29-
IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator();
34+
IEnumerator IEnumerable.GetEnumerator() => source2.GetEnumerator();
3035

3136
// Implement ICollection<TestValueType>
3237

33-
public int Count => source.Count;
38+
public int Count => source2.Count;
3439

3540
public bool IsReadOnly => true;
3641

@@ -54,10 +59,10 @@ public void CopyTo(Span<TestValueType> span)
5459
}
5560

5661
[MethodImpl(MethodImplOptions.AggressiveInlining)]
57-
public bool Contains(TestValueType item) => source.Contains(item);
62+
public bool Contains(TestValueType item) => source2.Contains(item);
5863

5964
[MethodImpl(MethodImplOptions.AggressiveInlining)]
60-
public void CopyTo(TestValueType[] array, int arrayIndex) => source.CopyTo(array, arrayIndex);
65+
public void CopyTo(TestValueType[] array, int arrayIndex) => source2.CopyTo(array, arrayIndex);
6166
}
6267
}
6368
}

NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithInterfacelessPublicEnumerator.cs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,47 @@ static partial class GeneratedExtensionMethods
1111
{
1212

1313
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
public static AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_ AsValueEnumerable(this TestEnumerableWithInterfacelessPublicEnumerator<TestValueType> source) => new(source);
14+
public static AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_<TestEnumerableWithInterfacelessPublicEnumerator<TestValueType>> AsValueEnumerable(this TestEnumerableWithInterfacelessPublicEnumerator<TestValueType> source)
15+
=> new(source, source);
1516

16-
public readonly struct AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_: IValueEnumerable<TestValueType, ValueEnumerator<TestValueType>>
17+
public readonly struct AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_<TEnumerable>
18+
: IValueEnumerable<TestValueType, AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_<TEnumerable>.Enumerator>
19+
where TEnumerable : IEnumerable<TestValueType>
1720
{
1821
readonly TestEnumerableWithInterfacelessPublicEnumerator<TestValueType> source;
22+
readonly TEnumerable source2;
1923

20-
internal AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_(TestEnumerableWithInterfacelessPublicEnumerator<TestValueType> source) => this.source = source;
24+
internal AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_(TestEnumerableWithInterfacelessPublicEnumerator<TestValueType> source, TEnumerable source2)
25+
=> (this.source, this.source2) = (source, source2);
2126

22-
// Implement IValueEnumerable<TestValueType, ValueEnumerator<TestValueType>>
27+
// Implement IValueEnumerable<TestValueType, AsValueEnumerable_TestEnumerableWithInterfacelessPublicEnumerator_TestValueType_<TEnumerable>.Enumerator>
2328

2429
[MethodImpl(MethodImplOptions.AggressiveInlining)]
25-
public TestEnumerableWithInterfacelessPublicEnumerator<TestValueType>.Enumerator GetEnumerator() => source.GetEnumerator();
30+
public Enumerator GetEnumerator() => new(source.GetEnumerator());
2631

27-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28-
ValueEnumerator<TestValueType> IValueEnumerable<TestValueType, ValueEnumerator<TestValueType>>.GetEnumerator() => new(((IEnumerable<TestValueType>)source).GetEnumerator());
32+
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => new Enumerator(source.GetEnumerator());
33+
34+
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(source.GetEnumerator());
35+
36+
public struct Enumerator : IEnumerator<TestValueType>
37+
{
38+
readonly TestEnumerableWithInterfacelessPublicEnumerator<TestValueType>.Enumerator source;
39+
40+
internal Enumerator(TestEnumerableWithInterfacelessPublicEnumerator<TestValueType>.Enumerator source)
41+
=> this.source = source;
42+
43+
public TestValueType Current => source.Current;
44+
45+
object? IEnumerator.Current => source.Current;
46+
47+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
48+
public bool MoveNext() => source.MoveNext();
2949

30-
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => ((IEnumerable<TestValueType>)source).GetEnumerator();
50+
public void Reset() => throw new NotSupportedException();
3151

32-
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<TestValueType>)source).GetEnumerator();
52+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
53+
public void Dispose() { }
54+
}
3355
}
3456
}
3557
}

NetFabric.Hyperlinq.SourceGenerator.UnitTests/TestData/Results/AsValueEnumerable.TestEnumerableWithNoInterfaces.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,32 @@ static partial class GeneratedExtensionMethods
1111
{
1212

1313
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14-
public static AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_ AsValueEnumerable(this TestEnumerableWithNoInterfaces<TestValueType> source) => new(source);
14+
public static AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_ AsValueEnumerable(this TestEnumerableWithNoInterfaces<TestValueType> source)
15+
=> new(source);
1516

16-
public readonly struct AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_: IValueEnumerable<TestValueType, AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_.Enumerator>
17+
public readonly struct AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_
18+
: IValueEnumerable<TestValueType, AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_.Enumerator>
1719
{
1820
readonly TestEnumerableWithNoInterfaces<TestValueType> source;
1921

20-
internal AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_(TestEnumerableWithNoInterfaces<TestValueType> source) => this.source = source;
22+
internal AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_(TestEnumerableWithNoInterfaces<TestValueType> source)
23+
=> this.source = source;
2124

2225
// Implement IValueEnumerable<TestValueType, AsValueEnumerable_TestEnumerableWithNoInterfaces_TestValueType_.Enumerator>
2326

2427
[MethodImpl(MethodImplOptions.AggressiveInlining)]
25-
public TestEnumerableWithNoInterfaces<TestValueType>.Enumerator GetEnumerator() => source.GetEnumerator();
26-
27-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28-
Enumerator IValueEnumerable<TestValueType, Enumerator>.GetEnumerator() => new(source.GetEnumerator());
28+
public Enumerator GetEnumerator() => new(source.GetEnumerator());
2929

3030
IEnumerator<TestValueType> IEnumerable<TestValueType>.GetEnumerator() => new Enumerator(source.GetEnumerator());
3131

3232
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(source.GetEnumerator());
3333

34-
public struct Enumerator: IEnumerator<TestValueType>
34+
public struct Enumerator : IEnumerator<TestValueType>
3535
{
3636
readonly TestEnumerableWithNoInterfaces<TestValueType>.Enumerator source;
3737

38-
internal Enumerator(TestEnumerableWithNoInterfaces<TestValueType>.Enumerator source) => this.source = source;
38+
internal Enumerator(TestEnumerableWithNoInterfaces<TestValueType>.Enumerator source)
39+
=> this.source = source;
3940

4041
public TestValueType Current => source.Current;
4142

0 commit comments

Comments
 (0)