Comparing byte arrays in C#, or at least, trying to …
Update 21st Sep 2009: Use the SequenceEqual extension method in LINQ.
For example:
byte[] array1 = new byte[] { 1, 2, 3, 4 };
byte[] array2 = new byte[] { 1, 2, 3, 4 };
bool areEqual = array1.SequenceEqual(array2); //returns true
Forgive me for thinking that in the following code two of the three evaluations should return true. They do not – they all return false.
byte[] array1 = new byte[] { 1, 2, 3, 4 };
byte[] array2 = new byte[] { 1, 2, 3, 4 };
bool result;
result = array1 == array2; // returns false (and should, because it’s referential)
result = array1.Equals(array2); // returns false (I think it should be true)
result = Array.Equals(array1, array2); // returns false (I think it should be true)
In my scenario I need to compare two arrays of exactly 8 bytes. Because of this specific length I can cheat a bit and convert them each to Int64 and then do the comparison:
bool result = BitConverter.ToInt64(byteArray1, 0) == BitConverter.ToInt64(byteArray2, 0);
Why isn’t this implemented at the framework level? It’s one simple method in the Array class:
[Serializable]
public abstract class Array : ICloneable, IList
{
public static override bool Equals(object obj)
{
Array array1 = this;
Array array2 = obj as Array;
// If the other object is null, of a diffent type, or
// of an array of a different length then skip out now.
if (array2 == null ||
array1.Length != array2.Length)
return false;
// If any of the elements are not equal, skip out.
for (int i = 0; i++; i < array1.Length)
if (array1.GetValue(i) != array2.GetValue(i))
return false;
// They’re both the same length and the elements are all
// equal so consider the arrays to be equal.
return true;
}
}
Does anybody know the reasoning behind this?
Update: Microsoft’s reponse is: "This is by design. Array.Equals() is just Object.Equals(), which compares the identity of the objects, not their contents. If you want to determine if 2 arrays have the same contents, you need to write a loop to compare the elements yourself." I don’t agree with that.



Totally silly … I’ve run into all kinds of silly things like that, especially with their data structures. MS needs to sweat the details more on stuff like this, and worry a little less about all the frameworks built on this stuff.
kindageeky
July 2, 2008 at 04:22
What on earth ever happened to memcmp ?
radsdau
July 7, 2008 at 10:26
What if you compare the hashcode? that would be an ideal comparison, no?
Like NoOther
July 18, 2008 at 01:05
Hi LikeNoOther,
Nice idea, but unfortunately they didn’t override the GetHashCode method in the array class. The default Object.GetHashCode implementation will be used instead which returns the sync block index of the object instance. Net effect will be the same as doing Object.Equals – different instances will not be considered equal even if they contain the same data.
Good try though.
Tatham
Tatham Oddie
July 18, 2008 at 09:15
1- I agree with MS designers not overriding Array.Equals as it’s supposed to provide “value-like” behaviour. As a design best practice we should be consistent around == and != operators and also overriding Object.Equals method. BUT, I do 100% agree framework is missing something like Array.CompareContent!
2- “memcpy” is already being used internally by System.Buffer. and perhaps MS folks would use “memcmp” internally easing Array.CompareContent implementation, BUT exposing such methods has issues with OO paradigm IMO, and higher level approaches are okay with almost same performance.
3- as Taham said hash-value comparison won’t help work as Array doesn’t implement content-based hash generation. however, not a good idea generating hash-value in the sake of content comparison – performance issues in particular.
Well, don’t understand why MS guys haven’t added such a helper method since even the very first version!
Jamal Mavadat
July 22, 2008 at 03:10
From System.Linq:
Enumerable.SequenceEqual();
or
Console.WriteLine(new byte[] {1,2,3}.SequenceEqual(new byte[] {1,2,3}));
RichB
November 4, 2008 at 23:23
Great tip Richard! I’ll add it to the post.
Tatham Oddie
November 5, 2008 at 08:12
If you are not using Linq
Pleas try
Convert.ToBase64String(array1)==Convert.ToBase64String(array2)
jojan
January 30, 2009 at 04:05
[...] http://blog.tatham.oddie.com.au/2008/07/01/comparing-byte-arrays-in-c-or-at-least-trying-to/ [...]
Comparing Byte Arrays in C# and more specifically using the .NET 3.5 Framework - Andrew Rea
February 20, 2009 at 21:17
There are two things wrong with your method:
1. You can’t have both static and override modifiers on the same method – I presume this was a typo;
2. Your method only works for vectors; multi-dimensional arrays would take a lot more effort.
Richard
February 24, 2009 at 06:24
Hi,
This technique is gud for me to compare to byte[] arrays.
Convert.ToBase64String(array1)==Convert.ToBase64String(array2)
Thanks!!
Hemant Kumar
April 15, 2009 at 15:02
Microsoft is correct in their explanation. I think as you become more experienced with OO languages it will make more sense.
However, I wanted to explain why some of the suggestions here should not be used.
1: Convert.ToBase64String(array1)==Convert.ToBase64String(array2)
The problems with this are as follows:
a: You are always getting the worst possible performance out of this. Without first checking the lengths of the arrays to be sure they are equal then you will always end up processing both arrays entirely.
b: Terrible runtime performance. You are iterating across all of array1 and array2 to convert them to strings, then iterating across both resulting strings to check equality. This will do twice as much work as just iterating through them and comparing the array byte values. Just because a method is provided by the runtime does not make it any faster than doing it manually(in most cases).
c: Terrible memory use. Although the strings are only used for a moment, there is a price to pay for allocating them.
I would write more but now I am tired of all of this.
-Tim
Tim
July 3, 2009 at 10:18
If you don’t want to create your own class, just use this helper method somewhere.
private static bool CompareByteArrays(byte[] array1, byte[] array2)
{
if (array1.Length != array2.Length)
return false;
for (int i = 0; i < array1.Length; i++)
if (array1[i] != array2[i])
return false;
return true;
}
Good luck!
=D Kees
Kees C. Bakker
August 11, 2009 at 19:15
public static bool ValueCompare(this T[] a, T[] b) where T: struct
{
if (a.Length != b.Length)
return false;
EqualityComparer q = EqualityComparer.Default;
for (int i = 0; i < a.Length; i++)
if (!q.Equals(a[i],b[i]))
return false;
return true;
}
Glenn Slayden
August 20, 2009 at 15:14
The angle brackets for the generic argument T were stripped off my posting by your blog. It belongs after the function name “ValueCompare” and also after the EqualityComparer.
Glenn Slayden
August 20, 2009 at 15:18
[...] fourni la solution propre recherchée avec c# 3.5 : http://blog.tatham.oddie.com.au/2008/07/01/comparing-byte-arrays-in-c-or-at-least-trying-to/ Publié dans General | Commentaires [...]
La billeterie » Blog Archive » c# comparaison de tableaux
January 18, 2010 at 22:06