CrumblyRock
CrumblyRock

Reputation: 371

Comparing equality of nested hashsets

I have a situation where I need to compare the equality of nested hashsets to determine if they contain the same elements or not. Here is a quick example that illustrates the problem:

    public void HashsetComparison()
    {
        var set1 = new HashSet<string> { "A", "B", "C" };
        var set2 = new HashSet<string> { "B", "C", "A" };
        var set3 = new HashSet<string> { "D", "E" };
        var set4 = new HashSet<string> { "D", "E" };

        //both currently return true
        var test1 = set1.SetEquals(set2);
        var test2 = set3.SetEquals(set4);

        var set5 = new HashSet<HashSet<string>> { set1, set3 };
        var set6 = new HashSet<HashSet<string>> { set2, set4 };

        //currently returns false
        var test3 = set5.SetEquals(set6);
    }

I need to figure out what to change in order to get test3 to return true. From the debugging that I have done, it seems like the HashSet.SetEquals() method is asking its children to get their hash codes and using those to compare for equality, which makes sense.

I've looked through some of the similar questions on StackOverflow, but haven't found one that has completely explained it to me yet. Do I need to implement a custom IEqualityComparer for the HashSet or is there something more obvious that I'm doing incorrectly?

Upvotes: 3

Views: 318

Answers (1)

Servy
Servy

Reputation: 203829

When you create the sets of sets, you're not providing a comparer, so the default comparer will be used, which will compare the sets based on their references. The use of SetEquals will uses the comparers of the sets, rather than allowing a comparer to be passed to those methods.

You need to pass a comparer to these two sets that compares them based on their values, rather than their references. Fortunately HashSet<T> already provides a method to create such a comparer:

var set5 = new HashSet<HashSet<string>>(HashSet<string>.CreateSetComparer()) 
{ set1, set3 };
var set6 = new HashSet<HashSet<string>>(HashSet<string>.CreateSetComparer()) 
{ set2, set4 };

Upvotes: 5

Related Questions