Consider this code:
public static void Main()
{
var item = new Item { Id = 1 };
IList list = new List<Item> { item };
IList array = new[] { item };
var newItem = new Item { Id = 1 };
var lIndex = list.IndexOf(newItem);
var aIndex = array.IndexOf(newItem);
Console.WriteLine(lIndex);
Console.WriteLine(aIndex);
}
public class Item : IEquatable<Item>
{
public int Id { get; set; }
public bool Equals(Item other) => other != null && other.Id == Id;
}
Results:
0
-1
Why are the results different between List<T>
and Array
? I guess this is by design, but why?
Looking at the code of List<T>.IndexOf
makes me wonder even more, since it's porting to Array.IndexOf
.
Implementation of IndexOf
in array class calls method:
public static int IndexOf(Array array, object value, int startIndex, int count)
As you see, it uses object
as value parameter. In this method there is code:
object obj = objArray[index];
if (obj != null && obj.Equals(value))
return index;
Classs works with objects, so it calls public virtual bool Equals(object obj)
method, not generic one.
In List
class IndexOf
uses generic implementation:
public static int IndexOf<T>(T[] array, T value, int startIndex, int count)
So, it uses generic quality comparer:
EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
UPD: I wrote a little post about this problem: http://blog.rogatnev.net/2017/07/14/IndexOf-with-IEquatable.html