How to convert linq results to HashSet or HashedSet
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Converting a LINQ result into a set is straightforward in modern .NET, but the exact method depends on which set type you mean. For normal .NET code, you usually want HashSet<T>, created either with ToHashSet() or with the HashSet<T> constructor. HashedSet<T> usually refers to an older third-party type and is much less common today.
Use ToHashSet() in modern .NET
If your target framework supports it, the cleanest option is ToHashSet():
This materializes the LINQ query and removes duplicates at the same time. It is the most readable option when the framework version provides the extension method.
The constructor works everywhere HashSet<T> exists
If ToHashSet() is not available, you can use the constructor:
This is the older, widely compatible answer. Functionally, it does the same job: enumerate the LINQ results and insert them into a hash-based set.
Use a comparer when equality rules matter
Set conversion is not only about removing duplicates. It is also about defining what counts as the same value. For strings, that often means passing a comparer:
Without the comparer, "Apple" and "apple" are different entries in a default case-sensitive set.
What about HashedSet<T>?
HashedSet<T> is usually associated with older libraries such as Iesi Collections, often seen in old NHibernate-related code. If you are working in ordinary modern .NET code, HashSet<T> is almost always the right choice.
If you truly need HashedSet<T> for a legacy codebase, the pattern is similar:
That is a legacy interoperability case, not the mainstream answer for current C# development.
Why convert at all
A set is useful when you care about uniqueness and fast membership checks. For example:
- removing duplicates from a query result
- turning a list of IDs into a quick lookup structure
- doing set operations such as union or intersection
If ordering matters, a set may be the wrong final shape because HashSet<T> is not designed as an ordered collection.
Deferred execution still matters
Remember that LINQ queries are often lazily evaluated. Converting to HashSet<T> forces immediate execution. That is usually what you want, but it is worth being explicit about it because the query will run at conversion time, not earlier.
Common Pitfalls
- Looking for
HashedSet<T>when standard .NET code should useHashSet<T>. - Forgetting that converting to a set removes duplicates by design.
- Ignoring custom equality rules such as case-insensitive string comparison.
- Assuming
HashSet<T>preserves LINQ ordering in a meaningful way. - Forgetting that
ToHashSet()is not available on every older target framework.
Summary
- In modern .NET, convert LINQ results to
HashSet<T>withToHashSet()or the constructor. - Use the constructor when framework support for
ToHashSet()is unavailable. - Pass an equality comparer when uniqueness rules need customization.
- '
HashedSet<T>is usually a legacy-library concern, not the normal modern answer.' - Converting to a set materializes the query and removes duplicates at the same time.

