Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EqualityComparer<T>.Default misunderstanding?

I have a class Person, it implements Equals() method from IEquatable<Person> (also overrides Object.Equals method, lets ignore the GetHashcode() method for now)

class Person : IEquatable<Person>
{
    public string Name { get; set; }

    public bool Equals(Person other)
    {
        return this.Name == other.Name;
    }
    public override bool Equals(object obj)
    {
        var person = obj as Person;
        return person != null && person.Name == Name;
    }
}

Ok, lets start:

Person p1 = new Person() { Name = "a" };
Person p2 = new Person() { Name = "a" };

List<Person> lst1 = new List<Person>() { p1 };
List<Person> lst2 = new List<Person>() { p2 };

Lets talk about this line :

 bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);

I have a problem understanding this part :

EqualityComparer<Person>.Default

I've heard that EqualityComparer<Person>.Default will check if the class is implementing IEquatable - it will take the Equals(Person other) Method and not the Equals(object obj). it has the advantage of avoiding boxing

enter image description herebut

the Equals(Person other) will run with or withOUT EqualityComparer<Person>.Default (because it's implementing IEquatable)

So what Boxing are we talking about ? there isn't !

The only time that Equals(object obj) will run is when :

bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);

But I'm a programmer! I'll never Send an object when its actually a Person!

What am I missing? I'm having trouble understanding the benefit here of EqualityComparer<Object>.Default. Can someone please give me an example to prove me I'm wrong ?

like image 404
Royi Namir Avatar asked Nov 04 '22 04:11

Royi Namir


2 Answers

That you can pass in IEqualityComparer<object>.Default is an effect of generic contravariance, added in .NET 4.

Essentially, an IEqualityComparer<BaseType> can be used whenever an IEqualityComparer<DerivedType> is required, where DerivedType : BaseType. Since Person derives from Object, this means that an IEqualityComparer<Object> can be used wherever an IEqualityComparer<Person> is required.

like image 157
thecoop Avatar answered Nov 09 '22 07:11

thecoop


If you pass in null as the second parameter or if you don't pass in a second argument at all (which is basically the same), the implementation of SequenceEquals will call EqualityComparer<T>.Default itself (decompile Enumerable to see this). That explains why you don't see a difference whether you provide EqualityComparer<T>.Default or not.

So in the end the second parameter only makes sense if you want to use an equality comparer other than EqualityComparer<T>.Default.

like image 42
Andre Loker Avatar answered Nov 09 '22 07:11

Andre Loker