I've been experimenting with implementing Set equality (ie List comparisons where the order is irrelevant) and after reading SO questions like this and this, wrote the following simple extension:
public static bool SetEqual<T>(this IEnumerable<T> enumerable, IEnumerable<T> other)
{
if (enumerable == null && other == null)
return true;
if (enumerable == null || other == null)
return false;
var setA = new HashSet<T>(enumerable);
return setA.SetEquals(other);
}
However, I came across a simple data structure for which this approach does not work, while Enumerable.SequenceEqual does.
public class Test : IEquatable<Test>
{
public Guid Id { get; set; }
public List<Test> RelatedTest { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != typeof(Test)) return false;
return Equals((Test)obj);
}
public bool Equals(Test other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return other.Id.Equals(Id) &&
RelatedTest.SetEqual(other.RelatedTest);
}
}
Given this object, this test succeeds:
[Test]
public void SequenceEqualTest()
{
var test1 = new List<Test> {new Test()};
var test2 = new List<Test> {new Test() };
Assert.That(test1.SequenceEqual(test2), Is.True);
}
But this test fails:
[Test]
public void SetEqualTest()
{
var test1 = new List<Test> {new Test()};
var test2 = new List<Test> {new Test()};
Assert.That(test1.SetEqual(test2), Is.True);
}
Does anyone have an explanation?