views:

756

answers:

5

Other than stepping through the elements one by one, how do I compare two lists of strings for equality (in .NET 3.0):

This fails:

        // Expected result.
        List<string> expected = new List<string>();
        expected.Add( "a" );
        expected.Add( "b" );
        expected.Add( "c" );

        // Actual result
        actual = new List<string>();
        actual.Add( "a" );
        actual.Add( "b" );
        actual.Add( "c" );

        // Verdict
        Assert.IsTrue( actual == expected );

Thanks in advance

+8  A: 

Try the following

var equal = expected.SequenceEquals(actual);

Test Version

Assert.IsTrue( actual.SequenceEquals(expected) );

The SequenceEquals extension method will compare the elements of the collection in order for equality.

JaredPar
Thansk for your answer. Is that .NET 3.5 only? I forgot to mention I'm using .NET 3.0.
Adam Kane
@Adam, yes. SequenceEquals is an extension method defined in 3.5 although it's fairly easy to port to a 2.0 project.
JaredPar
It won't give you details about why collections are different whereas CollectionAssert.AreEqual() will.
Konstantin Spirin
+5  A: 

Many test frameworks offer a CollectionAssert class:

CollectionAssert.AreEqual(expected, actual);
dahlbyk
+3  A: 

You can always write the needed function themselves:

public static bool ListEquals<T>(IList<T> list1, IList<T> list2) {
    if (list1.Count != list2.Count)
        return false;
    for (int i = 0; i < list1.Count; i++)
        if (!list1[i].Equals(list2[i]))
            return false;
    return true;
}

and use it:

// Expected result.
List<string> expected = new List<string>();
expected.Add( "a" );
expected.Add( "b" );
expected.Add( "c" );

// Actual result
actual = new List<string>();
actual.Add( "a" );
actual.Add( "b" );
actual.Add( "c" );

// Verdict
Assert.IsTrue( ListEquals(actual, expected) );
DreamWalker
Nice! I was looking to avoid stepping through the elments, but that's a great generic way you wrote the method.
Adam Kane
+3  A: 

I noticed no one actually told you why your original code didn't work. This is because the == operator in general tests reference equality (i.e. if the two instances are pointing to the same object in memory) unless the operator has been overloaded. List<T> does not define an == operator so the base reference equals implementation is used.

As other posters have demonstrated, you will generally have to step through elements to test "collection equality." Of course, you should use the optimization suggested by user DreamWalker which first tests the Count of the collections before stepping through them.

bobbymcr
+1  A: 

You could write an extension method like so:

public static class ListExtensions
    {
        public static bool IsEqual<T>(this IList<T> list,IList<T> target, IComparer<T> comparer) where T:IComparable<T>
        {
            if (list.Count != target.Count)
            {
                return false;
            }
            int index = 0;
            while (index < list.Count && 
                   comparer.Compare(list[index],target[index]) == 0)
            {
                index++;
            }
            if (index != list.Count)
            {
                return false;
            }
            return true;
        }
    }

And call it like so:

List<int> intList = new List<int> { 1, 234, 2, 324, 324, 2 };
List<int> targetList = new List<int> { 1, 234, 2, 324, 324 };
bool isEqual = intList.IsEqual(targetList, Comparer<int>.Default);

EDIT: Updated the code to use a static method instead since OP is using .NET 3.0

public static bool IsEqual<T>(IList<T> sourceList, IList<T> targetList, IComparer<T> comparer) where T : IComparable<T>
        {
            if (sourceList.Count != targetList.Count)
            {
                return false;
            }
            int index = 0;
            while (index < sourceList.Count &&
                   comparer.Compare(sourceList[index], targetList[index]) == 0)
            {
                index++;
            }
            if (index != sourceList.Count)
            {
                return false;
            }
            return true;
        }

Client:

        bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default);
Abhijeet Patel
Is it allowed in .NET 3.0?
Adam Kane
@Adam: I realised that you are using .NET 3.0 and not .NET 3.5 I'll edit my answer to make the code usable for .NET 3.0 by making it a static method instead of an extension method
Abhijeet Patel