7

Have I just forgotten the obvious, or is the "manual" comparer the best way to go?

Basically, I just want to compare the contents of type (small) byte-arrays. If all bytes match, the result should be true, otherwise false.

I was expecting to find that Array.Equals or Buffer.Equals would help.

Demonstration Code:

  var a = new byte[]{1, 2, 3, 4, 5};
  var b = new byte[]{1, 2, 3, 4, 5};
  Console.WriteLine(string.Format("== : {0}", (a == b)));
  Console.WriteLine(string.Format("Equals : {0}", a.Equals(b)));
  Console.WriteLine(string.Format("Buffer.Equals : {0}", Buffer.Equals(a, b)));
  Console.WriteLine(string.Format("Array.Equals = {0}", Array.Equals(a, b)));
  Console.WriteLine(string.Format("Manual_ArrayComparer = {0}", ArrayContentsEquals(a, b)));

Manual function:

/// <summary>Returns true if all elements of both byte-arrays are identical</summary>
public static bool ArrayContentsEquals(byte[] a, byte[] b, int length_to_compare = int.MaxValue)
{
  if (a == null || b == null) return false;
  if (Math.Min(a.Length, length_to_compare) != Math.Min(b.Length, length_to_compare)) return false;
  length_to_compare = Math.Min(a.Length, length_to_compare);
  for (int i = 0; i < length_to_compare; i++) if (a[i] != b[i]) return false;
  return true;
}
Steven_W
  • 848
  • 1
  • 7
  • 17
  • `Array.Equals`, `Buffer.Equals` etc are really the same thing: `Object.Equals`. As both `Array` and `Buffer`derive from `Object`, you're just calling the static `Object.Equals` method using a derived type name. This will check reference equality. – Lucas Trzesniewski Mar 05 '15 at 11:54
  • I've just seen the `SequenceEqual` option in [this question](http://stackoverflow.com/questions/1389570/c-sharp-byte-array-comparison-issue) – Steven_W Mar 05 '15 at 11:55
  • 1
    `best` isn't a good metric :-) Speed, compatibility, shortness of writing, easiness of comprehension, ... – xanatos Mar 05 '15 at 12:13

1 Answers1

16

You are looking for SequenceEqual method.

a.SequenceEqual(b);

Determines whether two sequences are equal by comparing the elements by using the default equality comparer for their type.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • 2
    It should be noted that `SequenceEqual` seems to be implemented in a way to just iterate over both enumerations and compare element by element, and return false if one enumeration ends sooner than the other. If many comparisons are made between many arrays of different length, checking whether the lengths match first would be a more sensible approach. – O. R. Mapper Mar 05 '15 at 11:56
  • Thanks - it is certainly "one" of the things I'd missed (before I looked at the answers to related questions) - Not sure if has a "shortcut-to-false" option if the byte[] arrays are different lengths... But at least I've got something to look at. I wasn't sure If `Buffer` and `Array` implemented their own overload of the simple `Object` or not - hence the reason for checkin. – Steven_W Mar 05 '15 at 11:58
  • @Steven_W: "Not sure if has a "shortcut-to-false" option if the byte[] arrays are different lengths..." - well, I'm sure, I just checked what the actual assemblies do with [ILSpy](http://ilspy.net/). – O. R. Mapper Mar 05 '15 at 12:00
  • the reference is available over at referencesource.microsoft.com as well. Here's [SequenceEqual](http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,63644a881e976b52) – default Mar 05 '15 at 12:13
  • Although I've marked this as "the answer", I do also appreciate the additional comments such as the one by @xanatos - `SequenceEqual` was the *inbuilt* function that I'd missed, but the manual approach (and linked question) also have their merits, for clarity, speed, etc... In this case, I'm only comparing about 8 bytes (and not in a performance-critical section), so will probably stick with the manual approach - Thanks to all. – Steven_W Mar 05 '15 at 12:41