tags:

views:

328

answers:

3

Precisely which methods in a Class are responsible for the List<T>'s Contains() to operate?

I have overloaded == in my class. But it seems to have no effect.

+10  A: 

It will just call Equals() - that's all that needs to be overridden (or not, if you're happy with reference identity comparisons). If the type implements IEquatable<T> then that implementation will be used in preference to the general Equals(object) though.

In particular, from the documentation for List<T>.Contains:

This method determines equality using the default equality comparer EqualityComparer(T).Default for T, the type of values in the list.

And from EqualityComparer<T>.Default:

The Default property checks whether type T implements the System.IEquatable(T) generic interface and if so returns an EqualityComparer(T) that uses that implementation. Otherwise it returns an EqualityComparer(T) that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

I don't believe it will use GetHashCode at all though.

Jon Skeet
+1  A: 

It will either call Object.Equals() or, if you have implemented, IEquatable<T>.Equals():

private static EqualityComparer<T> CreateComparer()
{
 Type c = typeof(T);
 if (c == typeof(byte))
 {
  return (EqualityComparer<T>) new ByteEqualityComparer();
 }
 if (typeof(IEquatable<T>).IsAssignableFrom(c))
 {
  return (EqualityComparer<T>) typeof(GenericEqualityComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(c);
 }
 if (c.IsGenericType && (c.GetGenericTypeDefinition() == typeof(Nullable<>)))
 {
  Type type2 = c.GetGenericArguments()[0];
  if (typeof(IEquatable<>).MakeGenericType(new Type[] { type2 }).IsAssignableFrom(type2))
  {
   return (EqualityComparer<T>) typeof(NullableEqualityComparer<int>).TypeHandle.CreateInstanceForAnotherGenericParameter(type2);
  }
 }
 return new ObjectEqualityComparer<T>();
}
Anton Gogolev
+2  A: 

From the .NET guidelines - if you implement == always provide an implementation for object.Equals() and the != operator. The reason is that operators are not part of any interface and their use is not allowed in generic implementations (a List class cannot call the == operator on T because there is no guarantee that T will have the operator defined (see structs for example)).

AZ