This is a followup question to this: List<T>.Contains and T[].Contains behaving differently
T[].Contains
is behaving differently when T
is class and struct. Suppose I have this struct:
public struct Animal : IEquatable<Animal>
{
public string Name { get; set; }
public bool Equals(Animal other) //<- he is the man
{
return Name == other.Name;
}
public override bool Equals(object obj)
{
return Equals((Animal)obj);
}
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
}
var animals = new[] { new Animal { Name = "Fred" } };
animals.Contains(new Animal { Name = "Fred" }); // calls Equals(Animal)
Here, generic Equals
is rightly called as I expected.
But in case of a class:
public class Animal : IEquatable<Animal>
{
public string Name { get; set; }
public bool Equals(Animal other)
{
return Name == other.Name;
}
public override bool Equals(object obj) //<- he is the man
{
return Equals((Animal)obj);
}
public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
}
var animals = new[] { new Animal { Name = "Fred" } };
animals.Contains(new Animal { Name = "Fred" }); // calls Equals(object)
The non generic Equals
is called, taking away the benefit of implementing `IEquatable.
Why is array calling Equals
differently for struct[]
and class[]
, even though both the collections seem to look generic?
The array weirdness is so frustrating that I'm thinking of avoiding it totally...
Note: The generic version of Equals
is called only when the struct implements IEquatable<T>
. If the type doesn't implement IEquatable<T>
, non-generic overload of Equals
is called irrespective of whether it is class
or struct
.
T[]
thing. I was just learning. – PotheadIEquatable<T>
is that it avoids boxing, which only matters for structs. There is still a minor gain from the generic method for classes, but the benefit is far smaller compared with structs. – ExcrescencyContains
on arrays after having forgotten to override non genericEquals
(soContains
did a reference equality check). – Pothead