Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing arrays in C#

Tags:

arrays

c#

People also ask

Can we compare two character arrays in C?

From the documentation on strcmp: Compares the C string str1 to the C string str2. This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.

Can we directly compare two array?

Java provides a direct method Arrays. equals() to compare two arrays. Actually, there is a list of equals() methods in the Arrays class for different primitive types (int, char, ..etc) and one for Object type (which is the base of all classes in Java).


Providing that you have LINQ available and don't care too much about performance, the easiest thing is the following:

var arraysAreEqual = Enumerable.SequenceEqual(a1, a2);

In fact, it's probably worth checking with Reflector or ILSpy what the SequenceEqual methods actually does, since it may well optimise for the special case of array values anyway!


"Why do i get that error?" - probably, you don't have "using System.Collections;" at the top of the file - only "using System.Collections.Generic;" - however, generics are probably safer - see below:

static bool ArraysEqual<T>(T[] a1, T[] a2)
{
    if (ReferenceEquals(a1,a2))
        return true;

    if (a1 == null || a2 == null)
        return false;

    if (a1.Length != a2.Length)
        return false;

    EqualityComparer<T> comparer = EqualityComparer<T>.Default;
    for (int i = 0; i < a1.Length; i++)
    {
        if (!comparer.Equals(a1[i], a2[i])) return false;
    }
    return true;
}

For .NET 4.0 and higher, you can compare elements in array or tuples using the StructuralComparisons type:

object[] a1 = { "string", 123, true };
object[] a2 = { "string", 123, true };
        
Console.WriteLine (a1 == a2);        // False (because arrays is reference types)
Console.WriteLine (a1.Equals (a2));  // False (because arrays is reference types)
        
IStructuralEquatable se1 = a1;
//Next returns True
Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer)); 

Recommending SequenceEqual is ok, but thinking that it may ever be faster than usual for(;;) loop is too naive.

Here is the reflected code:

public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, 
    IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
    if (comparer == null)
    {
        comparer = EqualityComparer<TSource>.Default;
    }
    if (first == null)
    {
        throw Error.ArgumentNull("first");
    }
    if (second == null)
    {
        throw Error.ArgumentNull("second");
    }
    using (IEnumerator<TSource> enumerator = first.GetEnumerator())     
    using (IEnumerator<TSource> enumerator2 = second.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            if (!enumerator2.MoveNext() || !comparer.Equals(enumerator.Current, enumerator2.Current))
            {
                return false;
            }
        }
        if (enumerator2.MoveNext())
        {
            return false;
        }
    }
    return true;
}

As you can see it uses 2 enumerators and fires numerous method calls which seriously slow everything down. Also it doesn't check length at all, so in bad cases it can be ridiculously slower.

Compare moving two iterators with beautiful

if (a1[i] != a2[i])

and you will know what I mean about performance.

It can be used in cases where performance is really not so critical, maybe in unit test code, or in cases of some short list in rarely called methods.


SequenceEqual can be faster. Namely in the case where almost all of the time, both arrays have indeed the same length and are not the same object.

It's still not the same functionality as the OP's function, as it won't silently compare null values.