In short, I am looking for guidance on which of the following two methods should be preferred (and why):
static IEnumerable<T> DistinctA<T>(this IEnumerable<T> xs)
{
return new HashSet<T>(xs);
}
static IEnumerable<T> DistinctB<T>(this IEnumerable<T> xs) where T : IEquatable<T>
{
return new HashSet<T>(xs);
}
Argument in favour of
DistinctA
: Obviously, the constraint onT
is not required, becauseHashSet<T>
does not require it, and because instances of anyT
are guaranteed to be convertible toSystem.Object
, which provides the same functionality asIEquatable<T>
(namely the two methodsEquals
andGetHashCode
). (While the non-generic methods will cause boxing with value types, that's not what I'm concerned about here.)Argument in favour of
DistinctB
: The generic parameter constraint, while not strictly necessary, makes visible to callers that the method will compare instances ofT
, and is therefore a signal thatEquals
andGetHashCode
should work correctly forT
. (After all, defining a new type without explicitly implementingEquals
andGetHashCode
happens very easily, so the constraint might help catch some errors early.)
Question: Is there an established and documented best practice that recommends when to specify this particular constraint (T : IEquatable<T>
), and when not to? And if not, is one of the above arguments flawed in any way? (In that case, I'd prefer well-thought-out arguments, not just personal opinions.)