LogIn
I don't have account.

HashSet<T>.CreateSetComparer() in C#

Ajeet Pawar
30 Views

When working with sets in C#, comparing two HashSet objects is not as simple as comparing two lists or arrays. That's because a HashSet is an unordered collection and two sets containing the same elements in different orders are still considered equal.

This is where the HashSet.CreateSetComparer() method comes into play. it allows developers to compare two sets based on their contents, not their memory references or order of elements.

Let’s explore this method in-depth including how it works, examples for value and reference types and real-world use cases. By the end, you'll understand how to accurately compare sets in C# and when to use this powerful method for efficient, clean and reliable code.

What is CreateSetComparer() in C#?

CreateSetComparer() is a static method of the HashSet class that creates an equality comparer capable of comparing two HashSet instances based on their set content.

Syntax

public static IEqualityComparer<HashSet<T>> CreateSetComparer();

Description

  • Returns an object implementing IEqualityComparer<HashSet>.

  • Compares two sets for value equality (i.e., both sets contain the same elements).

  • Order of elements doesn’t matter.

  • Duplicate elements don’t affect equality, since HashSet inherently prevents duplicates.

Why Use CreateSetComparer()?

Normally, when you compare two HashSet objects using the == operator or the .Equals() method, you're actually comparing their object references, not their actual contents.

That means even if two sets contain the exact same elements, they'll still be considered unequal because they are two different instances in memory.

Example (Without CreateSetComparer):


var set1 = new HashSet<int> { 1, 2, 3 };
var set2 = new HashSet<int> { 1, 2, 3 };

Console.WriteLine(set1.Equals(set2)); // False (different instances)

Even though both sets contain the same elements, Equals() returns false because they are two different objects in memory.

Solution – Use HashSet.CreateSetComparer()

  • With CreateSetComparer(), you can compare them by value (content) instead of by reference.

The CreateSetComparer() method provides an IEqualityComparer<HashSet> that compares two sets based on their values, not references. This means if both sets contain the same elements (regardless of order), they’ll be considered equal.


var set1 = new HashSet<int> { 1, 2, 3 };
var set2 = new HashSet<int> { 3, 1, 2 };

var comparer = HashSet<int>.CreateSetComparer();
Console.WriteLine(comparer.Equals(set1, set2)); 
// True — because both sets contain the same elements

With CreateSetComparer(), equality now truly means same elements, regardless of order, making it ideal for comparing sets in collections lookups or nested data structures

Using CreateSetComparer() with Reference Types in C#

When you use HashSet.CreateSetComparer() with reference types, the equality comparison depends on how equality is defined for those objects.

By default, reference types (like custom classes) are compared by reference, not by their field values. So, if you create two different instances with the same data, they’ll be considered different unless you override equality members (Equals() and GetHashCode()).

Example : Without Overriding Equality Members


class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
}

var set1 = new HashSet<Student> { new Student { Name = "Alex", Age = 22 } };
var set2 = new HashSet<Student> { new Student { Name = "Alex", Age = 22 } };

var comparer = HashSet<Student>.CreateSetComparer();
Console.WriteLine(comparer.Equals(set1, set2)); 
//False — even though both sets look identical

Why false? Because each Student object is a separate instance. The default equality check only compares references, not properties.

Solution 1: With Overridden Equals() and GetHashCode()

To make CreateSetComparer() compare by value, you must define what equal means for your custom class.


class Student
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is not Student other) return false;
        return Name == other.Name && Age == other.Age;
    }

    public override int GetHashCode() => HashCode.Combine(Name, Age);
}

var set1 = new HashSet<Student> { new Student { Name = "Alex", Age = 22 } };
var set2 = new HashSet<Student> { new Student { Name = "Alex", Age = 22 } };

var comparer = HashSet<Student>.CreateSetComparer();
Console.WriteLine(comparer.Equals(set1, set2)); 
//True — because equality is now based on Name and Age

Learn in depth : Why overriding Equals and GetHashCode both

In short:

  • For value types, CreateSetComparer() works out of the box.
  • For reference types, you must define equality logic in your class for meaningful comparisons.

Solution 2: Using a Custom IEqualityComparer (When You Can’t Modify the Class)

Sometimes you may not have control over the class definition for example, when it's part of a third-party library or you simply don't want to modify its code just to override Equals() and GetHashCode().

In such cases, you can provide a custom IEqualityComparer when constructing your HashSet.

The best part?

  • HashSet.CreateSetComparer() automatically respects and uses that custom comparer when comparing sets.

Example: Custom Comparer for Student Class (Without Modifying It)


class Student
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Custom comparer to define equality logic externally
class StudentComparer : IEqualityComparer<Student>
{
    public bool Equals(Student x, Student y)
    {
        if (x is null || y is null) return false;
        return x.Name == y.Name && x.Age == y.Age;
    }

    public int GetHashCode(Student obj)
    {
        return HashCode.Combine(obj.Name, obj.Age);
    }
}
var comparer = new StudentComparer();

var set1 = new HashSet<Student>(comparer)
{
    new Student { Name = "Alex", Age = 22 },
    new Student { Name = "John", Age = 23 }
};

var set2 = new HashSet<Student>(comparer)
{
    new Student { Name = "John", Age = 23 },
    new Student { Name = "Alex", Age = 22 }
};

var setComparer = HashSet<Student>.CreateSetComparer();

Console.WriteLine(setComparer.Equals(set1, set2));
// True — uses StudentComparer internally
How It Works Internally

When you create a HashSet with a custom IEqualityComparer:

  • The HashSet stores that comparer internally.

  • When you call HashSet.CreateSetComparer(), the returned comparer uses the same internal equality logic for element comparison.

  • This ensures consistent behavior across all operations — no need to override Equals() or GetHashCode() in your model class.

Final Thoughts

HashSet.CreateSetComparer() is one of those lesser-known but highly powerful methods in the .NET framework. It transforms how we compare collections, making equality semantic rather than referential , crucial in algorithms, caching and advanced data structures.

If you’re dealing with sets of sets, unique group tracking or nested collection equality, CreateSetComparer() is the right tool for the job.

Responses (0)

Write a response

CommentHide Comments

No Comments yet.