为什么 Array.IndexOf 不像 List<T> 那样检查 IEquatable?

Why is Array.IndexOf not checking for IEquatable like List<T> does?

考虑 this 代码:

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;

}

结果:

0
-1

为什么 List<T>Array 的结果不同?我想这是设计使然,但为什么呢?

查看 List<T>.IndexOf 的代码让我更加疑惑,因为它正在移植到 Array.IndexOf

因为通用对象集合在 ContainsIndexOfLastIndexOfRemove 等方法中测试相等性时使用 IEquatable<T> 接口。

Array 对 <T> 一无所知,因此它无法实现或使用 IEquatable 接口。

数组反而包含非通用对象。它将调用 Equals 将一个对象与另一个对象进行比较,因为所有对象都有一个 Equals 方法,您可以自由覆盖该方法。

List<T> 可以使用 IEquatable<T> 接口,这样就可以正常工作了。

数组正在使用 Object 中的 Equals 方法,您并没有覆盖那个方法,而只是实现了 IEquatable.

尝试像这样定义 Equals

public override bool Equals(Object other) => other != null && (other as Item).Id == Id;

这两种情况都适用。

在数组 class 中执行 IndexOf 调用方法:

public static int IndexOf(Array array, object value, int startIndex, int count)

如您所见,它使用 object 作为值参数。在这个方法中有代码:

object obj = objArray[index];
if (obj != null && obj.Equals(value))
    return index;

类与对象一起工作,因此它调用 public virtual bool Equals(object obj) 方法,而不是通用方法。

List class IndexOf中使用通用实现:

public static int IndexOf<T>(T[] array, T value, int startIndex, int count)

因此,它使用通用质量比较器:

EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);

UPD:关于这个问题我写了一点post:http://blog.rogatnev.net/2017/07/14/IndexOf-with-IEquatable.html