views:

349

answers:

3

Hi!

I am doing some byte[] comparisons.

I tried == but this is just like the base Equals, which:

byte[] a = {1,2,3};
byte[] b = {1,2,3};
bool equals = a == b; //false
equals = a.Equals(b); //false

I tried to add an extension method, but since the overloaded base class' Equals takes the same arguments, it goes to the base method rather to the extension, is there anyway I can use an Equals extension (wthout changing it's name...) or (even better) use == operator?

Here is what I actually have to Compare:

public static bool ContentEquals(this byte[] array, byte[] bytes)
{
    if (array == null || bytes == null) throw new ArgumentNullException();
    if( array.Length != bytes.Length) return false;
    for (int i = 0; i < array.Length; i++)
        if (array[i] != bytes[i]) return false;

    return true;
}
+4  A: 

You certainly can't do operator overloading with extension methods. The reason it doesn't work for the Equals method is that if any method is applicable without using extension methods, that method will be chosen before extension methods are even examined.

Even though your Equals method is "better" in terms of converting the argument types to the formal parameter types, the compiler always prefers "normal" methods. You'll have to give your method a different name.

However, you can always use the Enumerable.SequenceEquals method. I don't believe that short-circuits the length check though (even though it could, for ICollection<T> implementations). You could always implement a more efficient version yourself though. Indeed, if you just change your existing array implementation to be called SequenceEquals or even ArrayEquals, that would be fine:

public static bool ArrayEquals(this byte[] array, byte[] bytes)
{
    // I'd personally use braces in all of this, but it's your call
    if (array.Length != bytes.Length) return false;
    for (int i = 0; i < array.Length; i++)     
        if (array[i] != bytes[i]) return false;

    return true;
}

Note that it would be quite nice to make it generic, but that would certainly cost a bit of performance as the comparison couldn't be inlined:

public static bool ArrayEquals<T>(this T[] first, T[] second)
{
    // Reference equality and nullity checks for safety and efficiency
    if (first == second)
    {
        return true;
    }
    if (first == null || second == null)
    {
        return false;
    }
    if (first.Length != second.Length)
    {
        return false;
    }        
    EqualityComparer<T> comparer = EqualityComparer<T>.Default;
    for (int i = 0; i < first.Length; i++)
    {
        if (!comparer.Equals(first[i], second[i]))
        {
             return false;
        }
    }
    return true;
}
Jon Skeet
Shouldn't your first, non-generic method also check for reference equality and nullity?
Tommy Carlier
@Tommy: I wanted to leave the first version as close to the original as possible, but provide a fuller solution with more changes.
Jon Skeet
Wouldn't it be better to null check before doing the equality comparison? Or are you just doing this assuming that two null arrays are considered equal?
Hawker
+2  A: 
using System.Linq;

byte[] a = {1,2,3}; 
byte[] b = {1,2,3}; 
bool same = a.SequenceEqual(b);
Anonymous
A: 

I did this for the same purpose:

static class Global
{
    public static bool ArraysAreEqual(Array arr1, Array arr2)
    {
        if (arr1.Length != arr2.Length)
            return false;

        System.Collections.IEnumerator e1 = arr1.GetEnumerator();
        System.Collections.IEnumerator e2 = arr2.GetEnumerator();

        while(e1.MoveNext() && e2.MoveNext())
        {
            if(!e1.Current.Equals(e2.Current))
                return false;
        }
        return true;
    }
}

but notice that the .Equals() may even return false on reference-types when they are equal (I did not the test, but you can try with StringBuilder ). In my particular case I have only simple value-types

sergiol
Unless u use a really backwords .NET version, I don't understand why you bother your self after having this answer http://stackoverflow.com/questions/1054459/i-wanna-have-an-extension-method-equals-between-2-byte-arrays/3106129#3106129
Shimmy