How to compare arrays in C#?

C#ArraysCompare

C# Problem Overview


> Possible Duplicate:
> Easiest way to compare arrays in C#

How can I compare two arrays in C#?

I use the following code, but its result is false. I was expecting it to be true.

Array.Equals(childe1,grandFatherNode);

C# Solutions


Solution 1 - C#

You can use the Enumerable.SequenceEqual() in the System.Linq to compare the contents in the array

bool isEqual = Enumerable.SequenceEqual(target1, target2);

Solution 2 - C#

You're comparing the object references, and they are not the same. You need to compare the array contents.

.NET2 solution

An option is iterating through the array elements and call Equals() for each element. Remember that you need to override the Equals() method for the array elements, if they are not the same object reference.

An alternative is using this generic method to compare two generic arrays:

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;

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

.NET 3.5 or higher solution

Or use SequenceEqual if Linq is available for you (.NET Framework >= 3.5)

Solution 3 - C#

There is no static Equals method in the Array class, so what you are using is actually Object.Equals, which determines if the two object references point to the same object.

If you want to check if the arrays contains the same items in the same order, you can use the SequenceEquals extension method:

childe1.SequenceEqual(grandFatherNode)

###Edit: To use SequenceEquals with multidimensional arrays, you can use an extension to enumerate them. Here is an extension to enumerate a two dimensional array:

public static IEnumerable<T> Flatten<T>(this T[,] items) {
  for (int i = 0; i < items.GetLength(0); i++)
    for (int j = 0; j < items.GetLength(1); j++)
      yield return items[i, j];
}

Usage:

childe1.Flatten().SequenceEqual(grandFatherNode.Flatten())

If your array has more dimensions than two, you would need an extension that supports that number of dimensions. If the number of dimensions varies, you would need a bit more complex code to loop a variable number of dimensions.

You would of course first make sure that the number of dimensions and the size of the dimensions of the arrays match, before comparing the contents of the arrays.

###Edit 2: Turns out that you can use the OfType<T> method to flatten an array, as RobertS pointed out. Naturally that only works if all the items can actually be cast to the same type, but that is usually the case if you can compare them anyway. Example:

childe1.OfType<Person>().SequenceEqual(grandFatherNode.OfType<Person>())

Solution 4 - C#

Array.Equals is comparing the references, not their contents:

> Currently, when you compare two arrays with the = operator, we are really using the System.Object's = operator, which only compares the instances. (i.e. this uses reference equality, so it will only be true if both arrays points to the exact same instance)

Source

If you want to compare the contents of the arrays you need to loop though the arrays and compare the elements.

The same blog post has examples of how to do this. The basic implementation is:

public static bool ArrayEquals<T>(T[] a, T[] b)
{
    if (a.Length != b.Length)
    {
        return false;
    }

    for (int i = 0; i < a.Length; i++)
    {
        if (!a[i].Equals(b[i]))
        {
            return false;
        }
    }

    return true;
}

Though this will have performance issues. Adding a constraint:

public static bool ArrayEquals<T>(T[] a, T[] b) where T: IEquatable<T>

will improve things but will mean the code only works with types that implement IEquatable.

Using EqualityComparer.Default's Equal method instead of calling Equals on the types themselves will also improve performance without requiring the type to implement IEquatable. In this case the body of the method becomes:

    EqualityComparer<T> comparer = EqualityComparer<T>.Default;

    for (int i = 0; i < a.Length; i++)
    {
        if (!comparer.Equals(a[i], b[i]))
        {
            return false;
        }
    }

Solution 5 - C#

The Equals method does a reference comparison - if the arrays are different objects, this will indeed return false.

To check if the arrays contain identical values (and in the same order), you will need to iterate over them and test equality on each.

Solution 6 - C#

Array.Equals() appears to only test for the same instance.

There doesn't appear to be a method that compares the values but it would be very easy to write.

Just compare the lengths, if not equal, return false. Otherwise, loop through each value in the array and determine if they match.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmahdi View Question on Stackoverflow
Solution 1 - C#AMingView Answer on Stackoverflow
Solution 2 - C#Daniel PeñalbaView Answer on Stackoverflow
Solution 3 - C#GuffaView Answer on Stackoverflow
Solution 4 - C#ChrisFView Answer on Stackoverflow
Solution 5 - C#OdedView Answer on Stackoverflow
Solution 6 - C#Jonathan WoodView Answer on Stackoverflow