Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SequenceEqual different results

Tags:

c#

iequatable

in the code below calling SequenceEqual on generic list return true (as expected) when List is defined with class generic type (EquatableClass.Equals<> is called).

If list is defined with IEquatable interface, Equals method is not called and result is false (object.Equals is called instead, not in code).

The question is, why the EquatableClass.Equals<> method is not called in the second case?

public class EquatableClass : IEquatable<EquatableClass>
{
        public string Name { get; set; }
        public bool Equals(EquatableClass other) => this.Name.Equals(other.Name);        
}

static void Main(string[] args)
{
    var A = new List<EquatableClass> {  new EquatableClass { Name = "A" } };
    var B = new List<EquatableClass> {  new EquatableClass { Name = "A" } };

    var result1 = A.SequenceEqual(B); // == true;

    var AA = new List<IEquatable<EquatableClass>> {  new EquatableClass { Name = "A" } };
    var BB = new List<IEquatable<EquatableClass>> {  new EquatableClass { Name = "A" } };

    var result2 = AA.SequenceEqual(BB); // == false;    
}
like image 644
user4662448 Avatar asked Mar 21 '26 16:03

user4662448


1 Answers

The SequenceEqual<T> method will try to see if it can convert T to IEquatable<T>, and if it can, it will use IEquatable<T>.Equals for equality.

When you have a List<EquatableClass> it will then try to convert EquatableClass to IEquatable<EquatableClass>, and that succeeds, so it uses the appropriate Equals method.

When you have a List<IEquatable<EquatableClass>> it will then try to convert IEquatable<EquatableClass> to IEquatable<IEquatable<EquatableClass>>, and that will fail, because the actual object doesn't implement IEquatable<IEquatable<EquatableClass>>, so it resorts to the default behavior of using object.Equals(object), which you don't override.

like image 92
Servy Avatar answered Mar 24 '26 07:03

Servy