Is there a built-in method to compare collections?

I would like to compare the contents of a couple of collections in my Equals method. I have a Dictionary and an IList. Is there a built-in method to do this?

Edited: I want to compare two Dictionaries and two ILists, so I think what equality means is clear - if the two dictionaries contain the same keys mapped to the same values, then they're equal.


Solution 1:

Enumerable.SequenceEqual

Determines whether two sequences are equal by comparing their elements by using a specified IEqualityComparer(T).

You can't directly compare the list & the dictionary, but you could compare the list of values from the Dictionary with the list

Solution 2:

As others have suggested and have noted, SequenceEqual is order-sensitive. To solve that, you can sort the dictionary by key (which is unique, and thus the sort is always stable) and then use SequenceEqual. The following expression checks if two dictionaries are equal regardless of their internal order:

dictionary1.OrderBy(kvp => kvp.Key).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key))

EDIT: As pointed out by Jeppe Stig Nielsen, some object have an IComparer<T> that is incompatible with their IEqualityComparer<T>, yielding incorrect results. When using keys with such an object, you must specify a correct IComparer<T> for those keys. For example, with string keys (which exhibit this issue), you must do the following in order to get correct results:

dictionary1.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).SequenceEqual(dictionary2.OrderBy(kvp => kvp.Key, StringComparer.Ordinal))

Solution 3:

In addition to the mentioned SequenceEqual, which

is true if two lists are of equal length and their corresponding elements compare equal according to a comparer

(which may be the default comparer, i.e. an overriden Equals())

it is worth mentioning that in .Net4 there is SetEquals on ISet objects, which

ignores the order of elements and any duplicate elements.

So if you want to have a list of objects, but they don't need to be in a specific order, consider that an ISet (like a HashSet) may be the right choice.

Solution 4:

Take a look at the Enumerable.SequenceEqual method

var dictionary = new Dictionary<int, string>() {{1, "a"}, {2, "b"}};
var intList = new List<int> {1, 2};
var stringList = new List<string> {"a", "b"};
var test1 = dictionary.Keys.SequenceEqual(intList);
var test2 = dictionary.Values.SequenceEqual(stringList);

Solution 5:

This is not directly answering your questions, but both the MS' TestTools and NUnit provide

 CollectionAssert.AreEquivalent

which does pretty much what you want.