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
but
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 ?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With