views:

1585

answers:

4

Hello everyone,

I have two byte[] arrays in C#. And I am using VSTS 2008 + C# + .Net 3.0. What is the most efficient way to compare whether the two byte arrays contains the same content for each element?

For example, byte array {0x1, 0x2} is the same as {0x1, 0x2}, but byte array {0x1, 0x2} and byte array {0x2, 0x1} are not the same.

thanks in advance, George

+6  A: 

You can use the SequenceEqual method:

bool areEqual = firstArray.SequenceEqual(secondArray);

As mentioned in the comments, SequenceEqual requires .NET 3.5 (or LINQBridge if you're using VS2008 and targeting an earlier version of the framework).

LukeH
The most efficient way I think.
Veton
Not in terms of execution time it's not.
Jon Skeet
@Veton: It's certainly the least typing! See Jon's answer for a few additional optimisations.
LukeH
(Try comparing a byte array containing 1,000,000 entries with one containing 1,000,001 entries via SequenceEqual. It will go right to the end before noticing they have different lengths...)
Jon Skeet
This also doesn't work (without something like LINQBridge) in .NET 3.0 as required in the question... although it's possible that the OP meant .NET 3.5.
Jon Skeet
I am using .Net 3.0, seems this method only works in .Net 3.5. :-(
George2
+9  A: 

Well, you could use:

public bool ByteArraysEqual(byte[] b1, byte[] b2)
{
    if (b1 == b2) return true;
    if (b1 == null || b2 == null) return false;
    if (b1.Length != b2.Length) return false;
    for (int i=0; i < b1.Length; i++)
    {
        if (b1[i] != b2[i]) return false;
    }
    return true;
}

(I normally use braces for everything, but I thought I'd experiment with this layout style just for a change...)

This has a few optimisations which SequenceEqual can't (or doesn't) perform - such as the up-front length check. Direct array access will also be a bit more efficient than using the enumerator.

Admittedly it's unlikely to make a significant difference in most cases...

You could possibly make it faster in unmanaged code by making it compare 32 or 64 bits at a time instead of 8 - but I wouldn't like to code that on the fly.

Jon Skeet
I like your solution!
George2
Hey Jon, Do you work for stackoverflow ?
Shiva
@Shiva: Nope, I work for Google.
Jon Skeet
For large arrays, say 10k, would parallelizing be an efficient optimization or would the threading overhead be to too much?
Darren
+1  A: 

If you want it to be really fast, you can use unsafe code (which isn't always possible):

    public static bool ArraysEqual(byte[] b1, byte[] b2)
    {
        unsafe
        {
            if (b1.Length != b2.Length)
                return false;

            int n = b1.Length;

            fixed (byte *p1 = b1, p2 = b2)
            {
                byte *ptr1 = p1;
                byte *ptr2 = p2;

                while (n-- > 0)
                {
                    if (*ptr1++ != *ptr2++)
                        return false;
                }
            }

            return true;
        }
    }
Philippe Leybaert
+2  A: 

Jon mentioned comparing multiple bytes at once using unsafe code, so I had to give it a go:

public unsafe bool ByteArraysEqual(byte[] b1, byte[] b2) {
   if (b1 == b2) return true;
   if (b1 == null || b2 == null) return false;
   if (b1.Length != b2.Length) return false;
   int len = b1.Length;
   fixed (byte* p1 = b1, p2 = b2) {
      int* i1 = (int*)p1;
      int* i2 = (int*)p2;
      while (len >= 4) {
         if (*i1 != *i2) return false;
         i1++;
         i2++;
         len -= 4;
      }
      p1 = (byte*)i1;
      p2 = (byte*)i2;
      while (len > 0) {
         if (*p1 != *p2) return false;
         p1++;
         p2++;
         len--;
      }
   }
   return true;
}

The safe code gets pretty optimised (the compiler knows that it doesn't have to check index boundaries for example), so I wouldn't expect the unsafe code to be very much faster. Any significant difference would come from the ability to compare several bytes at once.

Guffa