在C#中,为什么数组上的Equals()方法只比较它们的引用,而不比较它们的实际内容

本文关键字:比较 引用 方法 数组 为什么 Equals | 更新日期: 2023-09-27 18:00:12

C#中,为什么Equals()方法总是通过比较引用而不是通过比较内容来检查两个arrays之间的相等性?

因此,所有在实现中调用Equals()的方法(很多)都不能像预期的那样与数组一起工作(它不会比较内容):

示例:

int[] array1 = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] array2 = new[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
var u = array1.Equals(array1);                                       //true
var v = array1.Equals(array2);                                       //false
var w = Array.Equals(array1, array2);                                //false
var x = (new List<int[]>(new int[][] { array1 })).Contains(array2);  //false
var y = (new int[][] { array1 }).Any(x => x == array2);              //false
var z = (new int[][] { array1, array2 }).Distinct().Count() == 1;    //false

处理数组(无论类型如何)的一种可能的通用方法是:

Object.Equals()中:如果要比较的两种类型都是数组(长度相同),则枚举项(总是可能的),对于每个项,调用Equals()。如果其中一个调用返回false,则数组不同(返回false),否则返回true

注意:我知道SequenceEqual()memcmp()和其他比较两个数组的方法。我的问题不是如何比较数组。我只是想知道为什么#的设计者不选择在Equals()方法中实现全数组比较。

在C#中,为什么数组上的Equals()方法只比较它们的引用,而不比较它们的实际内容

尽管微软的框架类在Object.Equals(Object)的含义上有点不一致,但通常只有当用Y的引用替换对X的任意引用时,X.Equals(Y)才是真的,反之亦然,这不会改变所讨论对象的语义。例如,如果X是内容为"Hello"的String,而Y是内容相同的不同字符串,则将对一个字符串的引用替换为对另一个的引用通常不会改变它们的行为。虽然使用ReferenceEquals测试两个字符串引用是否引用同一个字符串的代码可能会注意到切换,但普通的字符串代码不会。

一般来说,任何可变对象都不等价于任何其他对象,因此,除非两个引用都引用了相同的对象,否则对可变对象的引用都不应等价于另一个对象。对int[]的两个不同实例的引用都具有相同的值,与对同一实例的两个引用有很大区别。虽然Array具有ItemsEqual方法将有助于测试数组的所有项或某些项范围是否匹配,并且具有Equals/GetHashCode成员的ImmutableArray类型将视为相等的两个具有相同内容的不可变数组也将有帮助,无论内容如何,不同的可变数组之间的比较都是不相等的,这是完全正确和恰当的。