Comparing two List<string> for equality

49,025

Solution 1

Many test frameworks offer a CollectionAssert class:

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

Solution 2

Try the following

var equal = expected.SequenceEqual(actual);

Test Version

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

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

See http://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx

Solution 3

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) );

Solution 4

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.

Solution 5

If the order matters:

bool equal = a.SequenceEquals(b);

If the order doesn't matter:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);
Share:
49,025
Adam Kane
Author by

Adam Kane

Technical Director and Co-Founder for ForgeFX leading the development of simulation-based training software for industries including aerospace, construction, mining, agriculture, animal production, and emergency response. www.forgefx.com

Updated on July 08, 2022

Comments

  • Adam Kane
    Adam Kane almost 2 years

    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 );
    
  • Adam Kane
    Adam Kane over 14 years
    Nice! I was looking to avoid stepping through the elments, but that's a great generic way you wrote the method.
  • Adam Kane
    Adam Kane over 14 years
    Thansk for your answer. Is that .NET 3.5 only? I forgot to mention I'm using .NET 3.0.
  • JaredPar
    JaredPar over 14 years
    @Adam, yes. SequenceEquals is an extension method defined in 3.5 although it's fairly easy to port to a 2.0 project.
  • Konstantin Spirin
    Konstantin Spirin over 14 years
    It won't give you details about why collections are different whereas CollectionAssert.AreEqual() will.
  • Abhijeet Patel
    Abhijeet Patel over 14 years
    @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
  • Gatis Bergšpics
    Gatis Bergšpics almost 11 years
  • fbmd
    fbmd over 10 years
    You will need to add using System.Linq ; in order to be able to use the method as shown.
  • JHixson
    JHixson about 10 years
    Thank you! I could think of several ways of doing the comparison myself, but when I ran into this issue, I thought "Well, it obviously isn't checking for equality, so what IS it doing?"
  • Colonel Panic
    Colonel Panic almost 9 years
    Alas the messages it gives when it fails are slightly useless, eg. "Different number of elements" or "Element at index 0 do not match", without telling you what they are.
  • Mike Taverne
    Mike Taverne over 8 years
    Upvoted, this is a good answer. However, note that the function will throw an exception if either list is null. Recommend adding the following statements to the beginning of the function: if (list1 == null && list2 == null) return true; and if (list1 == null || list2 == null) return false;