34

I am checking the equality of two byte arrays, and I wanted some help because what I have returns false even though the arrays should be equal.

Within my debug I could see both of a1 and b1 are equal, but it is not going inside the while loop to increment i.

public bool Equality(byte[] a1, byte[] b1)
{
    int i;
    bool bEqual;
    if (a1.Length == b1.Length)
    {
        i = 0;
        while ((i < a1.Length) && (a1[i]==b1[i]))
        {
            i++;
        }

        if (i == a1.Length)
        {
            bEqual = true;
        }
    }
    return bEqual;
}

This always returns false: (a1[i]==b1[i]).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Masriyah
  • 2,445
  • 11
  • 49
  • 91

5 Answers5

61

You need to add a return value somewhere. This should work:

public bool Equality(byte[] a1, byte[] b1)
{
   int i;
   if (a1.Length == b1.Length)
   {
      i = 0;
      while (i < a1.Length && (a1[i]==b1[i])) //Earlier it was a1[i]!=b1[i]
      {
          i++;
      }
      if (i == a1.Length)
      {
          return true;
      }
   }

   return false;
}

But this is much simpler:

return a1.SequenceEqual(b1);

Alternatively, you could use IStructuralEquatable from .NET 4:

return ((IStructuralEquatable)a1).Equals(b1, StructuralComparisons.StructuralEqualityComparer)

If performance is a concern, I'd recommend rewriting your code to use the Binary class, which is specifically optimized for this kind of use case:

public bool Equality(Binary a1, Binary b1)
{
    return a1.Equals(b1);
}

A quick benchmark on my machine gives the following stats:

Method                   Min         Max         Avg
binary equal:          0.868       3.076       0.933    (best)
for loop:              2.636      10.004       3.065
sequence equal:        8.940      30.124      10.258
structure equal:     155.644     381.052     170.693

Download this LINQPad file to run the benchmark yourself.

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • i am using this to compare two different files and return the difference ( what records were added or removed) not that it runs and loops properly i am not getting a returned message about the difference of the files in which one file had records removed – Masriyah Aug 27 '13 at 18:36
  • @Masriyah So what you really want to do is implement a diff algorithm? That's an entirely different task than simply checking equality. I recommend you look at Google's [diff-match-patch](https://code.google.com/p/google-diff-match-patch/) library. – p.s.w.g Aug 27 '13 at 18:42
  • I went ahead and uploaded the other parts of my code which is relating to this. Maybe you can take a look and point something out. i've been running around in circles with this all day. thanks – Masriyah Aug 27 '13 at 18:50
  • 1
    Logically there is no difference between OP's code and this code as far as first solution is concerned. OP only forgot to initialize `bEqual` to false which if done would also yield the same result. – Imran Aug 27 '13 at 19:09
  • i posted a new question if you can take a look. http://stackoverflow.com/questions/18473580/returning-records-that-have-been-added-or-removed-after-two-file-comparison – Masriyah Aug 27 '13 at 19:10
  • StructuralComparisons has slower performance than the for loop – alhpe Mar 11 '19 at 12:14
  • @alhpe Yes. I've updated my answer with notes on performance. – p.s.w.g Mar 11 '19 at 16:55
  • It's a pity the Binary class doesn't exist in .net core :( – AnorZaken Nov 29 '19 at 10:10
  • You can also look into using `Span` - according to [this answer](https://stackoverflow.com/a/48599119/533837) it's very performant. – AnorZaken Nov 29 '19 at 16:04
43

To check equality you can just write:

var areEqual =  a1.SequenceEqual(b1);
Magnus
  • 45,362
  • 8
  • 80
  • 118
  • 3
    That technically requires LINQ which might not match his framework – Moop Aug 27 '13 at 18:35
  • 9
    But if it does match his framework it is a much better way of doing it. – Scott Chamberlain Aug 27 '13 at 18:36
  • 2
    @Moop Linq has been around for 6 years now, surely most people have upgraded to at least framework 3.5 by now. – Magnus Aug 27 '13 at 18:39
  • 4
    @MikePrecup in this day an age, ***unless explicitly specified***, I think it is safe to assume that any project being worked on is 3.5+. [67% of all .NET users are on version 4 and 26% are on some version of 3](http://web.archive.org/web/20120919192827/http://statowl.com/microsoft_dotnet.php). – Scott Chamberlain Aug 27 '13 at 18:52
6

I'd recommend some short-circuiting to make things a bit simpler, and use of object.ReferenceEquals to short-circuit for cases when the arrays are the same reference (a1 = b1):

public bool Equality(byte[] a1, byte[] b1)
{
    // If not same length, done
    if (a1.Length != b1.Length)
    {
        return false;
    }

    // If they are the same object, done
    if (object.ReferenceEquals(a1,b1))
    {
        return true;
    }

    // Loop all values and compare
    for (int i = 0; i < a1.Length; i++)
    {
        if (a1[i] != b1[i])
        {
            return false;
        }
    }

    // If we got here, equal
    return true;
}
Haney
  • 32,775
  • 8
  • 59
  • 68
1

This should work:

public bool Equality(byte[] a1, byte[] b1)
{
   if(a1 == null || b1 == null)
       return false;
   int length = a1.Length;
   if(b1.Length != length)
      return false;
   while(length >0) {
       length--;
       if(a1[length] != b1[length])
          return false;           
   }
   return true;        
}
Moop
  • 3,414
  • 2
  • 23
  • 37
0

You should add some return statements:

public bool Equality(byte[] a1, byte[] b1)
{
    int i = 0;
    if (a1.Length == b1.Length)
    {
        while ((i < a1.Length) && (a1[i]==b1[i]))
        {
            i++;
        }
    }
    return i == a1.Length;
}

Or, better yet

public bool Equality(byte[] a1, byte[] b1)
{
    if(a1.Length != b1.Length)
    {
        return false;
    }

    for (int i = 0; i < a1.Length; i++)
    {
        if (a1[i] != b1[i])
        {
            return false;
        }
    }
    return true;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131