Skip to content

Instantly share code, notes, and snippets.

@dombrovsky
Created May 1, 2023 08:12
Show Gist options
  • Save dombrovsky/ea95d2c9f614b57c21465a9af3cba1e4 to your computer and use it in GitHub Desktop.
Save dombrovsky/ea95d2c9f614b57c21465a9af3cba1e4 to your computer and use it in GitHub Desktop.
CollectionEqualityComparer
public static class CollectionEqualityComparer
{
public static IEqualityComparer<IReadOnlyCollection<T>> ForReadOnlyCollectionOf<T>(IEqualityComparer<T>? equalityComparer = null)
{
return new CollectionEqualityComparer<T, IReadOnlyCollection<T>>(equalityComparer ?? EqualityComparer<T>.Default);
}
public static IEqualityComparer<IReadOnlyList<T>> ForReadOnlyListOf<T>(IEqualityComparer<T>? equalityComparer = null)
{
return new CollectionEqualityComparer<T, IReadOnlyList<T>>(equalityComparer ?? EqualityComparer<T>.Default);
}
}
internal sealed class CollectionEqualityComparer<T, TCollection> : IEqualityComparer<TCollection>
where TCollection : IReadOnlyCollection<T>
{
private readonly IEqualityComparer<T> _equalityComparer;
public CollectionEqualityComparer()
: this(EqualityComparer<T>.Default)
{
}
public CollectionEqualityComparer(IEqualityComparer<T> equalityComparer)
{
Argument.NotNull(equalityComparer);
_equalityComparer = equalityComparer;
}
public bool Equals(TCollection? x, TCollection? y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (ReferenceEquals(x, null))
{
return false;
}
if (ReferenceEquals(y, null))
{
return false;
}
if (x.Count != y.Count)
{
return false;
}
return x.SequenceEqual(y, _equalityComparer);
}
public int GetHashCode(TCollection obj)
{
Argument.NotNull(obj);
return obj.Aggregate(0, (result, item) => (result * 397) ^ _equalityComparer.GetHashCode(item!));
}
}
[TestFixture]
public sealed class CollectionEqualityComparerFixture
{
private CollectionEqualityComparer<int, List<int>> _sut = null!;
[SetUp]
public void SetUp()
{
_sut = new CollectionEqualityComparer<int, List<int>>();
}
[Test]
public void Equals_WhenXIsNull_ReturnsFalse()
{
// Arrange
var y = new List<int>();
// Act
var result = _sut.Equals(null, y);
// Assert
Assert.False(result);
}
[Test]
public void Equals_WhenYIsNull_ReturnsFalse()
{
// Arrange
var x = new List<int>();
// Act
var result = _sut.Equals(x, null);
// Assert
Assert.False(result);
}
[Test]
public void Equals_WhenXAndYAreNull_ReturnsTrue()
{
// Act
var result = _sut.Equals(null, null);
// Assert
Assert.True(result);
}
[Test]
public void Equals_WhenXAndYHaveDifferentCounts_ReturnsFalse()
{
// Arrange
var x = new List<int> { 1, 2, 3 };
var y = new List<int> { 1, 2 };
// Act
var result = _sut.Equals(x, y);
// Assert
Assert.False(result);
}
[Test]
public void Equals_WhenXAndYHaveSameElements_ReturnsTrue()
{
// Arrange
var x = new List<int> { 1, 2, 3 };
var y = new List<int> { 1, 2, 3 };
// Act
var result = _sut.Equals(x, y);
// Assert
Assert.True(result);
}
[Test]
public void GetHashCode_WhenXAndYHaveSameElements_ReturnsSame()
{
// Arrange
var x = new List<int> { 1, 2, 3 };
var y = new List<int> { 1, 2, 3 };
// Assert
Assert.That(_sut.GetHashCode(x), Is.EqualTo(_sut.GetHashCode(y)));
}
[Test]
public void Equals_WhenXAndYHaveSameElementsInDifferentOrder_ReturnsFalse()
{
// Arrange
var x = new List<int> { 1, 2, 3 };
var y = new List<int> { 3, 2, 1 };
// Act
var result = _sut.Equals(x, y);
// Assert
Assert.False(result);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment