tags:

views:

8553

answers:

6

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.

+1  A: 

No, because it the framework doesn't know how to compare the contents of your lists.

Have a look at this:

http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx

Mark Ingram
+29  A: 

http://msdn.microsoft.com/en-us/library/bb342073.aspx

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

Glenn Slaven
The problem is that SequenceEqual expects the elements to be in the same order. The Dictionary class does not guarantee the order of keys or values when enumerating, so if you're going to use SequenceEqual, you have to sort the .Keys and .Values first!
Orion Edwards
+5  A: 

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);
aku
This is not reliable because SequenceEqual expects the values to come out of the dictionary in a reliable order - The dictionary makes no such guarantees about order, and dictionary.Keys could well come out as [2, 1] instead of [1, 2] and your test would fail
Orion Edwards
+1  A: 

I didn't know about Enumerable.SequenceEqual method (you learn something every day....), but I was going to suggest using an extension method; something like this:

    public static bool IsEqual(this List<int> InternalList, List<int> ExternalList)
    {
        if (InternalList.Count != ExternalList.Count)
        {
            return false;
        }
        else
        {
            for (int i = 0; i < InternalList.Count; i++)
            {
                if (InternalList[i] != ExternalList[i])
                    return false;
            }
        }

        return true;

    }

Interestingly enough, after taking 2 seconds to read about SequenceEqual, it looks like Microsoft has built the function I described for you.

Giovanni Galbo
+1  A: 

No. The collection framework doesn't have any concept of equality. If you think about it there is no way of comparing collections which isn't subjective. For instance comparing your IList to your Dictionary, would they be equal if all the keys were in the IList, all the values were in the IList or if both were in the IList? There is no obvious way of comparing these two collections without knowledge of what they are to be used for so a general purpose equals method makes no sense.

Evil Andy
+2  A: 

.NET Lacks any powerful tools for comparing collections. I've developed a simple solution you can find at the link below:

http://robertbouillon.com/2010/04/29/comparing-collections-in-net/

This will perform an equality comparison regardless of order:

var list1 = new[] { "Bill", "Bob", "Sally" };
var list2 = new[] { "Bob", "Bill", "Sally" };
bool isequal = list1.Compare(list2).IsSame;

This will check to see if items were added / removed:

var list1 = new[] { "Billy", "Bob" };
var list2 = new[] { "Bob", "Sally" };
var diff = list1.Compare(list2);
var onlyinlist1 = diff.Removed; //Billy
var onlyinlist2 = diff.Added;   //Sally
var inbothlists = diff.Equal;   //Bob

This will see what items in the dictionary changed:

var original = new Dictionary<int, string>() { { 1, "a" }, { 2, "b" } };
var changed = new Dictionary<int, string>() { { 1, "aaa" }, { 2, "b" } };
var diff = original.Compare(changed, (x, y) => x.Value == y.Value, (x, y) => x.Value == y.Value);
foreach (var item in diff.Different)
  Console.Write("{0} changed to {1}", item.Key.Value, item.Value.Value);
//Will output: a changed to aaa