为什么 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
。
因为通用对象集合在 Contains
、IndexOf
、LastIndexOf
和 Remove
等方法中测试相等性时使用 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
考虑 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
。
因为通用对象集合在 Contains
、IndexOf
、LastIndexOf
和 Remove
等方法中测试相等性时使用 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