11

In C#, why Equals() method always check equality between two arrays by comparing the references the and not by comparing the content ?

As a consequence, all methods calling Equals() in their implementation (a lot) does not work as expected with arrays (it does not compare the content) :

Example :

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

A possible generic way to handle arrays (no mater the type) could be :

In Object.Equals() : if both types to compare are arrays (of same length), enumerate items (always possible), for each item, call Equals(). If one of these calls return false, array are different (return false) otherwise return true.

Note : I know about SequenceEqual(), memcmp() and other ways to compare two arrays. My question is not about how to compare arrays. I just want to know why C# designers dont choose to implement a full array comparaison in Equals() method.

tigrou
  • 4,236
  • 5
  • 33
  • 59
  • 1
    Interesting question, even if it's going to be hard to answer it as given (the intersection of SO users and C# team members is a pretty small set). – Jon Feb 19 '13 at 14:46
  • 1
    We could theorize, but as the people who made the decision are highly unlikely to come here, none of us can realistically answer the question of what the C# team was thinking, even if we might know reasons we might not make the decision ourselves. – Servy Feb 19 '13 at 14:47
  • Consider two arrays with 100,000 elements each, containing very complex objects that each has it's own overriden `Equals` method which does deep inspection of the object to also consider equality. You could easily shoot yourself in the foot by doing what you might think is a simple equality check. – CodingGorilla Feb 19 '13 at 14:47
  • 1
    @CodingGorilla: Indeed, but `String.Equals` of course works, and the strings might be a couple of GB each. So the "string cuts it, array does not" division is in my eyes arbitrary. – Jon Feb 19 '13 at 14:48
  • MSDN[Obeject.Equals Method](http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) – MethodMan Feb 19 '13 at 14:49
  • @Jon I think you're a little more likely to understand that comparing two strings (of which you likely know the relative sizes) than you are to understand that comparing two arrays and possibly not understanding how deeply the inspection goes because you don't always know how a class implements `Equals` (IMHO). – CodingGorilla Feb 19 '13 at 14:50
  • 2
    @Some1.Kill.The.DJ, asking "*why* some particular implementation was chosen by the language designers" is *not* a good fit for this site. – Kirk Woll Feb 19 '13 at 14:51
  • Question is valid but a duplicate question [stackoverflow same question](http://stackoverflow.com/questions/649444/testing-equality-of-arrays-in-c-sharp) – MethodMan Feb 19 '13 at 14:51
  • 1
    @DJKRAZE, that's not even a dup. Asking *why* (and ignoring the how -- which the OP explicitly said he didn't care about) is why this questoin should remain closed. – Kirk Woll Feb 19 '13 at 14:52
  • 2
    @DJKRAZE That's not a duplicate at all. The question you linked is appropriate, this question is asking why the language designers did what they did, as opposed to how to check for equality with the OP here specifically said he *doesn't* need to know. – Servy Feb 19 '13 at 14:53
  • Either way Servy.. nobody can answer the question then.. however the link can provide the OP a means and or some direction how how to set up their comparison use case.. – MethodMan Feb 19 '13 at 15:02
  • I didn't know asking *why* things are implemented in a certain way was forbidden here. Also, my question was not to blame C# team or people who work on this (i am already convinced they did a good job) but rather to understand the reasons/compromises they chose. For example this guy (http://stackoverflow.com/questions/995255/why-is-multiple-inheritance-not-allowed-in-java-or-c) asked *why* no multiple inheritance is allowed in C# and java and question do not get downvoted or closed. – tigrou Feb 19 '13 at 15:13
  • 1
    @DJKRAZE The question *specifically* said he *wasn't* looking for that; clearly he's already familiar with it. – Servy Feb 19 '13 at 15:14
  • 1
    @tigrou That's a very old question from when SO hadn't yet narrowed it's scope; such questions are no longer appropriate. Additionally, just because there is another question that isn't closed that is not appropriate for the site doesn't mean yours shouldn't be closed; it just means some other question slipped through the cracks. As for why it's not appropriate, as I said, as none of the members here were on the C# team at the time, none of us can answer the question. If none of us can ever possibly answer the question, why should it be allowed? – Servy Feb 19 '13 at 15:16
  • @Servy: ok to admit my question being hard to answer or inappropriate. but not because i just asked *why*. question about *why* regarding language implementation are very common on SO : http://stackoverflow.com/questions/9983981/why-does-c-sharp-allow-multiple-inheritance-though-interface-extension-methods-b (april 2012). Also, no need of being part of C# team to answer the question, CodingGorilla already give one valid reason. – tigrou Feb 19 '13 at 15:26
  • 1
    @tigrou That's not answering your question. You didn't ask, "why might it be better for Array.Equals to use a reference comparison instead of a value comparison" because that question is at least answerable. Since he wasn't on the C# team when this decision was made he can't know if that's what they were thinking, which is *exactly* what you asked for. Even if that is the correct answer, just because it's coming from him means it can never answer *your* question. It's for exactly that reason that this question doesn't belong on SO. – Servy Feb 19 '13 at 15:36

1 Answers1

7

Although Microsoft's Framework classes are unfortunately a bit inconsistent with regard to what Object.Equals(Object) means, in general X.Equals(Y) will only be true if replacing arbitrary references to X with references to Y, and/or vice versa, would not be expected to alter the semantics of the objects in question. For example, if X is a String with the content "Hello", and Y is a different string with that same content, replacing references to one string with references to the other would not generally alter their behavior. Although code which uses ReferenceEquals to test whether two string references refer to the same string might notice the switch, normal string code would not.

As a general rule, no mutable object is equivalent to any other, and thus no reference to a mutable object should be equivalent to another unless both references refer to the same object. There is a big difference between having references to two different instances of int[], both of which hold the same values, versus having two references to the same instance. While it would be helpful for Array to have ItemsEqual methods which would test whether all items of the arrays, or certain ranges of items, matched, and it would be helpful to have an ImmutableArray type with a Equals/GetHashCode members that would regard as equal two immutable arrays with the same content, it is entirely right and proper that distinct mutable arrays compare unequal to each other regardless of content.

supercat
  • 77,689
  • 9
  • 166
  • 211