Skip to content

Commit e15133d

Browse files
committed
Adds EqualityComparer<T>.Create polyfill
1 parent 3e26030 commit e15133d

File tree

19 files changed

+103
-212
lines changed

19 files changed

+103
-212
lines changed

src/Compilers/CSharp/Test/Semantic/SourceGeneration/GeneratorDriverTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,7 +1500,7 @@ [Attr] class C { }
15001500
{
15011501
var name = ctx.ForAttributeWithSimpleName<ClassDeclarationSyntax>("Attr")
15021502
.Select((c, _) => c.Identifier.ValueText)
1503-
.WithComparer(new LambdaComparer<string>((_, _) => throw e));
1503+
.WithComparer(EqualityComparer<string>.Create((_, _) => throw e));
15041504
ctx.RegisterSourceOutput(name, (spc, n) => spc.AddSource(n, "// generated"));
15051505
});
15061506

@@ -1997,7 +1997,7 @@ class C { }
19971997

19981998
var generator = new IncrementalGeneratorWrapper(new PipelineCallbackGenerator(ctx =>
19991999
{
2000-
var compilationSource = ctx.CompilationProvider.WithComparer(new LambdaComparer<Compilation>((c1, c2) => true, 0));
2000+
var compilationSource = ctx.CompilationProvider.WithComparer(EqualityComparer<Compilation>.Create((_, _) => true, _ => 0));
20012001
ctx.RegisterSourceOutput(compilationSource, (spc, c) =>
20022002
{
20032003
compilationsCalledFor.Add(c);
@@ -2035,7 +2035,7 @@ class C { }
20352035
{
20362036
var compilationSource = ctx.CompilationProvider.Combine(ctx.AdditionalTextsProvider.Collect())
20372037
// comparer that ignores the LHS (additional texts)
2038-
.WithComparer(new LambdaComparer<(Compilation, ImmutableArray<AdditionalText>)>((c1, c2) => c1.Item1 == c2.Item1, 0))
2038+
.WithComparer(EqualityComparer<(Compilation, ImmutableArray<AdditionalText>)>.Create((c1, c2) => c1.Item1 == c2.Item1, _ => 0))
20392039
.WithTrackingName("Step")
20402040
.Select((x, ct) => x)
20412041
.WithTrackingName("Step2");

src/Compilers/CSharp/Test/Semantic/SourceGeneration/StateTableTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public void Node_Table_Caches_Previous_Object_When_Modification_Considered_Cache
233233
var expected = ImmutableArray.Create((1, EntryState.Added, 0), (2, EntryState.Added, 0), (3, EntryState.Added, 0));
234234
AssertTableEntries(previousTable, expected);
235235

236-
builder = previousTable.ToBuilder(stepName: null, false, new LambdaComparer<int>((i, j) => i == 3 || i == j));
236+
builder = previousTable.ToBuilder(stepName: null, false, EqualityComparer<int>.Create((i, j) => i == 3 || i == j));
237237
Assert.True(builder.TryModifyEntry(1, TimeSpan.Zero, default, EntryState.Modified)); // ((1, EntryState.Cached))
238238
Assert.True(builder.TryModifyEntry(4, TimeSpan.Zero, default, EntryState.Modified)); // ((4, EntryState.Modified))
239239
Assert.True(builder.TryModifyEntry(5, TimeSpan.Zero, default, EntryState.Modified)); // ((3, EntryState.Cached))
@@ -918,7 +918,7 @@ public void CombineNode_Records_Removed_Outputs_Of_Removed_First_Input()
918918
public void User_Comparer_Is_Not_Used_To_Determine_Inputs()
919919
{
920920
var inputNode = new InputNode<int>((_) => ImmutableArray.Create(1, 2, 3))
921-
.WithComparer(new LambdaComparer<int>((a, b) => false));
921+
.WithComparer(EqualityComparer<int>.Create((_, _) => false));
922922

923923
// first time through will always be added (because it's not been run before)
924924
DriverStateTable.Builder dstBuilder = GetBuilder(DriverStateTable.Empty);

src/Compilers/CSharp/Test/Semantic/SourceGeneration/SyntaxAwareGeneratorTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,7 +1513,7 @@ class C
15131513
var testGenerator = new PipelineCallbackGenerator(context =>
15141514
{
15151515
var source = context.SyntaxProvider.CreateSyntaxProvider((c, _) => c is FieldDeclarationSyntax fds, (c, _) => ((FieldDeclarationSyntax)c.Node).Declaration.Variables[0].Identifier.ValueText);
1516-
source = source.WithComparer(new LambdaComparer<string>((a, b) => true)).WithTrackingName("Fields");
1516+
source = source.WithComparer(EqualityComparer<string>.Create((a, b) => true)).WithTrackingName("Fields");
15171517
context.RegisterSourceOutput(source, (spc, fieldName) =>
15181518
{
15191519
});
@@ -1574,10 +1574,10 @@ class C
15741574
syntaxCalledFor.Add(((FieldDeclarationSyntax)c.Node).Declaration.Variables[0].Identifier.ValueText);
15751575
return ((FieldDeclarationSyntax)c.Node).Declaration.Variables[0].Identifier.ValueText;
15761576
});
1577-
source = source.WithComparer(new LambdaComparer<string>((a, b) => false));
1578-
source = source.WithComparer(new LambdaComparer<string>((a, b) => false));
1579-
source = source.WithComparer(new LambdaComparer<string>((a, b) => false));
1580-
source = source.WithComparer(new LambdaComparer<string>((a, b) => false));
1577+
source = source.WithComparer(EqualityComparer<string>.Create((a, b) => false));
1578+
source = source.WithComparer(EqualityComparer<string>.Create((a, b) => false));
1579+
source = source.WithComparer(EqualityComparer<string>.Create((a, b) => false));
1580+
source = source.WithComparer(EqualityComparer<string>.Create((a, b) => false));
15811581
context.RegisterSourceOutput(source, (spc, fieldName) => { });
15821582
});
15831583

@@ -1631,7 +1631,7 @@ class C
16311631
noCompareCalledFor.Add(fieldName);
16321632
});
16331633

1634-
var comparerSource = source.WithComparer(new LambdaComparer<string>((a, b) => true));
1634+
var comparerSource = source.WithComparer(EqualityComparer<string>.Create((a, b) => true));
16351635
context.RegisterSourceOutput(comparerSource, (spc, fieldName) =>
16361636
{
16371637
compareCalledFor.Add(fieldName);
@@ -1794,7 +1794,7 @@ class C
17941794
return ((FieldDeclarationSyntax)c.Node).Declaration.Variables[0].Identifier.ValueText;
17951795
}).WithTrackingName("Fields");
17961796

1797-
var comparerSource = source.WithComparer(new LambdaComparer<string>((a, b) => false));
1797+
var comparerSource = source.WithComparer(EqualityComparer<string>.Create((a, b) => false));
17981798

17991799
// now join the two sources together
18001800
var joinedSource = source.Combine(comparerSource.Collect());

src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/EnumerableExtensionsTests.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@ public ReadOnlyList(params T[] items)
6666
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
6767
}
6868

69-
private class SignlessEqualityComparer : IEqualityComparer<int>
70-
{
71-
public bool Equals(int x, int y) => Math.Abs(x) == Math.Abs(y);
72-
public int GetHashCode(int obj) => throw new NotImplementedException();
73-
}
74-
7569
[Fact]
7670
public void IndexOf()
7771
{
@@ -85,7 +79,7 @@ public void IndexOf()
8579
[Fact]
8680
public void IndexOf_EqualityComparer()
8781
{
88-
var comparer = new SignlessEqualityComparer();
82+
var comparer = EqualityComparer<int>.Create((x, y) => Math.Abs(x) == Math.Abs(y));
8983

9084
Assert.Equal(-1, SpecializedCollections.SingletonList(5).IndexOf(-6, comparer));
9185
Assert.Equal(0, SpecializedCollections.SingletonList(5).IndexOf(-5, comparer));
@@ -159,19 +153,10 @@ public void TestSequenceEqualWithFunction()
159153
Assert.False(seq.SequenceEqual(new int[] { 1, 2, 6 }, equality));
160154
}
161155

162-
public sealed class Comparer<T>(Func<T, T, bool> equals, Func<T, int> hashCode) : IEqualityComparer<T>
163-
{
164-
private readonly Func<T, T, bool> _equals = equals;
165-
private readonly Func<T, int> _hashCode = hashCode;
166-
167-
public bool Equals(T x, T y) => _equals(x, y);
168-
public int GetHashCode(T obj) => _hashCode(obj);
169-
}
170-
171156
[Fact]
172157
public void HasDuplicates()
173158
{
174-
var comparer = new Comparer<int>((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
159+
var comparer = EqualityComparer<int>.Create((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
175160

176161
Assert.False(MakeEnumerable<int>().HasDuplicates());
177162
Assert.False(MakeEnumerable<int>().HasDuplicates(comparer));

src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ImmutableArrayExtensionsTests.cs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void SetEquals()
9191
var equalElements = new int[] { -1, -2, -3 }.AsImmutableOrNull();
9292
var equalDuplicate = new int[] { 1, 2, 3, 3, -3 }.AsImmutableOrNull();
9393

94-
IEqualityComparer<int> comparer = new AbsoluteValueComparer();
94+
var comparer = EqualityComparer<int>.Create((x, y) => Math.Abs(x) == Math.Abs(y), Math.Abs);
9595

9696
Assert.True(nul.SetEquals(nul, comparer));
9797
Assert.True(empty.SetEquals(empty, comparer));
@@ -120,22 +120,6 @@ public void SetEquals()
120120
Assert.False(singleton1.SetEquals(singleton2, comparer));
121121
}
122122

123-
private class AbsoluteValueComparer : IEqualityComparer<int>
124-
{
125-
#region IEqualityComparer<int> Members
126-
127-
bool IEqualityComparer<int>.Equals(int x, int y)
128-
{
129-
return Math.Abs(x) == Math.Abs(y);
130-
}
131-
132-
int IEqualityComparer<int>.GetHashCode(int x)
133-
{
134-
return Math.Abs(x);
135-
}
136-
#endregion
137-
}
138-
139123
[Fact]
140124
public void Single()
141125
{
@@ -544,19 +528,10 @@ public void IsSubsetOf_Equal(int[] array, int[] other)
544528
Assert.True(other.ToImmutableArray().IsSubsetOf(array.ToImmutableArray()));
545529
}
546530

547-
public sealed class Comparer<T>(Func<T, T, bool> equals, Func<T, int> hashCode) : IEqualityComparer<T>
548-
{
549-
private readonly Func<T, T, bool> _equals = equals;
550-
private readonly Func<T, int> _hashCode = hashCode;
551-
552-
public bool Equals(T x, T y) => _equals(x, y);
553-
public int GetHashCode(T obj) => _hashCode(obj);
554-
}
555-
556531
[Fact]
557532
public void HasDuplicates()
558533
{
559-
var comparer = new Comparer<int>((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
534+
var comparer = EqualityComparer<int>.Create((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
560535

561536
Assert.False(ImmutableArray<int>.Empty.HasDuplicates());
562537
Assert.False(ImmutableArray<int>.Empty.HasDuplicates(comparer));

src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ListExtensionsTests.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,17 @@
44

55
#nullable disable
66

7-
using System;
87
using System.Collections.Generic;
9-
using Roslyn.Utilities;
108
using Xunit;
119

1210
namespace Microsoft.CodeAnalysis.UnitTests;
1311

1412
public class ListExtensionsTests
1513
{
16-
public sealed class Comparer<T>(Func<T, T, bool> equals, Func<T, int> hashCode) : IEqualityComparer<T>
17-
{
18-
private readonly Func<T, T, bool> _equals = equals;
19-
private readonly Func<T, int> _hashCode = hashCode;
20-
21-
public bool Equals(T x, T y) => _equals(x, y);
22-
public int GetHashCode(T obj) => _hashCode(obj);
23-
}
24-
2514
[Fact]
2615
public void HasDuplicates()
2716
{
28-
var comparer = new Comparer<int>((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
17+
var comparer = EqualityComparer<int>.Create((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
2918

3019
Assert.False(new int[0].HasDuplicates());
3120
Assert.False(new int[0].HasDuplicates(comparer));

src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableSegmentedHashSetBuilderTest.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -346,23 +346,12 @@ public void TryGetValue()
346346
var builder = ImmutableSegmentedHashSet.Create(1, 2, 3).ToBuilder();
347347
Assert.True(builder.TryGetValue(2, out _));
348348

349-
builder = ImmutableSegmentedHashSet.Create(CustomEqualityComparer.Instance, 1, 2, 3, 4).ToBuilder();
349+
var comparer = EqualityComparer<int>.Create((x, y) => x >> 1 == y >> 1, x => (x >> 1).GetHashCode());
350+
351+
builder = ImmutableSegmentedHashSet.Create(comparer, 1, 2, 3, 4).ToBuilder();
350352
var existing = 0;
351353
Assert.True(builder.TryGetValue(5, out existing));
352354
Assert.Equal(4, existing);
353355
}
354-
355-
private class CustomEqualityComparer : IEqualityComparer<int>
356-
{
357-
private CustomEqualityComparer()
358-
{
359-
}
360-
361-
public static CustomEqualityComparer Instance { get; } = new CustomEqualityComparer();
362-
363-
public bool Equals(int x, int y) => x >> 1 == y >> 1;
364-
365-
public int GetHashCode(int obj) => (obj >> 1).GetHashCode();
366-
}
367356
}
368357
}

src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableSegmentedListTest.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,9 @@ public void ReplaceWithEqualityComparerTest()
543543
{
544544
var list = ImmutableSegmentedList.Create(new Person { Name = "Andrew", Age = 20 });
545545
var newAge = new Person { Name = "Andrew", Age = 21 };
546-
var updatedList = list.Replace(newAge, newAge, new NameOnlyEqualityComparer());
546+
var nameOnlyComparer = EqualityComparer<Person>.Create((x, y) => x.Name == y.Name, x => x.Name.GetHashCode());
547+
548+
var updatedList = list.Replace(newAge, newAge, nameOnlyComparer);
547549
Assert.Equal(newAge.Age, updatedList[0].Age);
548550

549551
// Try again with a null equality comparer, which should use the default EQ.
@@ -945,18 +947,5 @@ private struct Person
945947
public string Name { get; set; }
946948
public int Age { get; set; }
947949
}
948-
949-
private class NameOnlyEqualityComparer : IEqualityComparer<Person>
950-
{
951-
public bool Equals(Person x, Person y)
952-
{
953-
return x.Name == y.Name;
954-
}
955-
956-
public int GetHashCode(Person obj)
957-
{
958-
return obj.Name.GetHashCode();
959-
}
960-
}
961950
}
962951
}

src/Compilers/Core/CodeAnalysisTest/InternalUtilities/OneOrManyTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
67
using System.Collections.Immutable;
78
using Microsoft.CodeAnalysis.Collections;
89
using Roslyn.Test.Utilities;
@@ -265,7 +266,7 @@ public void SequenceEqual()
265266
[Fact]
266267
public void SequenceEqual_WithComparer()
267268
{
268-
var comparer = new TestEqualityComparer<int>((x, y) => x % 10 == y % 10);
269+
var comparer = EqualityComparer<int>.Create((x, y) => x % 10 == y % 10);
269270
Assert.True(OneOrMany.Create(1).SequenceEqual(new[] { 11 }, comparer));
270271
Assert.True(OneOrMany.Create(1, 2).SequenceEqual(new[] { 11, 32 }, comparer));
271272
Assert.False(OneOrMany.Create(1, 2).SequenceEqual(new[] { 0, 1 }, comparer));

src/Compilers/Core/CodeAnalysisTest/Text/TextChangeTests.cs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -275,23 +275,12 @@ public void TestGetTextChangesToChangedText()
275275
}
276276
}
277277

278-
private sealed class TextLineEqualityComparer : IEqualityComparer<TextLine>
279-
{
280-
public bool Equals(TextLine x, TextLine y)
281-
{
282-
return x.Span == y.Span;
283-
}
284-
285-
public int GetHashCode(TextLine obj)
286-
{
287-
return obj.Span.GetHashCode();
288-
}
289-
}
290-
291278
private static void AssertChangedTextLinesHelper(string originalText, params TextChange[] changes)
292279
{
293280
var changedText = SourceText.From(originalText).WithChanges(changes);
294-
Assert.Equal(SourceText.From(changedText.ToString()).Lines, changedText.Lines, new TextLineEqualityComparer());
281+
var comparer = EqualityComparer<TextLine>.Create((x, y) => x.Span == y.Span, x => x.Span.GetHashCode());
282+
283+
Assert.Equal(SourceText.From(changedText.ToString()).Lines, changedText.Lines, comparer);
295284
}
296285

297286
[Fact]

0 commit comments

Comments
 (0)