10

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

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

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

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

4

1 回答 1

6

尽管不幸的是,Microsoft 的框架类在含义方面有点不一致Object.Equals(Object),但通常X.Equals(Y)只有在将任意引用替换为X对 的引用Y和/或反之亦然时才会如此,不会期望改变相关对象的语义。例如,如果XString内容为“Hello”的 a,并且Y是具有相同内容的不同字符串,则将对一个字符串的引用替换为对另一个字符串的引用通常不会改变它们的行为。尽管ReferenceEquals用于测试两个字符串引用是否引用同一个字符串的代码可能会注意到这个开关,但普通的字符串代码不会。

作为一般规则,没有可变对象与任何其他对象等价,因此对可变对象的引用不应与另一个对象等价,除非两个引用都指向同一个对象。对 的两个不同实例的引用与对同一个实例的两个引用之间存在很大差异int[],这两个实例都具有相同的值。虽然Array拥有ItemsEqual可以测试数组的所有项目或某些项目范围是否匹配的方法会很有帮助,并且有一个ImmutableArray带有Equals/GetHashCode成员的类型将被视为相等的两个不可变数组将是有帮助的相同的内容,无论内容如何,​​不同的可变数组相互比较是不相等的,这是完全正确和正确的。

于 2013-02-26T22:15:24.177 回答