HashSet in C# is a collection type that stores unique elements and does not allow duplicates. It is an unordered collection optimized for fast lookup, insertion, and removal using hashing. HashSet is ideal when we need to ensure unique data and perform set operations like unions, intersections, and differences efficiently.

List allows duplicate values and performs slower searches, because it checks items one by one.

HashSet, on the other hand, stores only unique values and offers much faster lookups due to its hash-based structure.

What is HashSet in C#

HashSet belongs to the System.Collections.Generic namespace and was introduced in .NET 3.5.

A HashSet<T> is a collection that implements the set data structure concept.

How Does it Achieve Uniqueness and Speed?

The Hashset achieves its speed and uniqueness by utilizing a technique called hashing.

  1. When an element is added, the set first calls the object's GetHashCode() method to calculate an integer hash code.

  2. This hash code determines a "bucket" or index where the element should be stored in the underlying data structure (often a specialized form of a hash table).

  3. To ensure uniqueness, the set then checks if an element with the exact same value already exists in that bucket by calling the object's Equals() method. If both the hash code and the value are equal to an existing element, the insertion is blocked.

This hash-based approach allows the runtime to quickly jump to the correct location in memory, resulting in blazing fast lookups.

HashSet Declaration and Syntax

The Hashset<T> syntax is straightforward and uses the C# Generics feature, where the <T> specifies the type of element the set will hold.

1. The using Directive

Because Hashset<T> is part of the Collections framework, we should always include the following at the top of your C# file:

using System.Collections.Generic;

2.Basic Declaration

HashSet<T> variableName = new HashSet<T>();

Example

Imagine building a feature for an event management system where we want to keep track of unique attendees' email addresses. Using a list would require extra code to check for duplicates manually. With HashSet, we can add email addresses directly, and it ensures no duplicates exist automatically:

HashSet<string> attendeeEmails = new HashSet<string>();
attendeeEmails.Add("[email protected]");
attendeeEmails.Add("[email protected]");
attendeeEmails.Add("[email protected]"); // This will be ignored, no duplicates allowed

foreach (var email in attendeeEmails)
    Console.WriteLine(email);

will be:

[email protected]
 [email protected]

Explanation

This behavior ensures no duplicates exist in the collection.

Common Operations in HashSet

1. Basic Manipulation Operations

MethodDescriptionExampleTime Complexity
Add(T item)Attempts to add a specified element to the set. Returns true if the element was added (it was unique), and false if the element already existed (it was ignored).mySet.Add("data");O(1)
Remove(T item)Removes the specified element from the set. Returns true if the element was successfully found and removed, and false otherwise.mySet.Remove("old");O(1)
Contains(T item)Checks if the specified element exists in the set. Returns true or false.mySet.Contains("test");O(1) (The most efficient lookup)
CountGets the number of elements currently in the set (a property, not a method).int count = mySet.Count;O(1)
Clear()Removes all elements from the HashSet.mySet.Clear();O(n)

2. Set Mathematics Operations

These methods allow you to compare and combine two HashSet objects based on mathematical set theory principles. These are the operations that truly differentiate HashSet from other collections like List<T>.

OperationMethodDescriptionAnalogy
UnionUnionWith(IEnumerable<T> other)Modifies the current set to contain all elements that are present in either the current set OR the other collection.Combining two contact lists into one master list.
IntersectionIntersectWith(IEnumerable<T> other)Modifies the current set to contain only the elements that are present in BOTH the current set AND the other collection.Finding the common users who belong to two separate security groups.
DifferenceExceptWith(IEnumerable<T> other)Modifies the current set by removing all elements that are also present in the other collection.Finding employees who are currently on the payroll but NOT signed up for the new training.
Symmetric DifferenceSymmetricExceptWith(IEnumerable<T> other)Modifies the current set to contain elements that are present in one set or the other, but NOT in both.Finding elements that are unique to Set A or unique to Set B (the elements on the "outside" of the intersection).

3. Subset and Superset Relations

MethodDescriptionAnalogy
IsSubsetOf(IEnumerable<T> other)Checks if the current set is entirely contained within the other collection. Returns true if every element in the current set is also in the other set.The Shopping List: Is everything on our small shopping list (current set) also available in the store's inventory (other set)?
IsSupersetOf(IEnumerable<T> other)Checks if the current set contains all the elements of the other collection. Returns true if the current set holds every element in the other set.The Recipe Ingredients: Does our pantry's contents (current set) contain all the mandatory ingredients required by the recipe (other set)?
Overlaps(IEnumerable<T> other)Checks if the two collections share at least one common element. Returns true if their intersection is not empty.The Movie Schedules: Do the showtimes for Movie A (current set) and Movie B (other set) conflict by sharing at least one common time slot?

HashSet use-cases and advantages

1. Eliminating Duplicate Data

HashSet is primarily used when we must ensure uniqueness. It automatically removes duplicates without extra validation code. This is useful in real-world scenarios like importing holidays, student roll numbers, product codes, or any data where repeated values must be avoided.

2. Fast Lookup Performance

HashSet provides very fast lookups because it uses hashing internally. Checking whether an item exists is almost instant, even in large collections. This makes it suitable for scenarios like verifying if an email, employee ID, or token has already been used.

3. Efficient Set Operations

HashSet supports built-in operations like Union, Intersection, and Difference. These operations help combine or compare lists efficiently. For example, finding common employees between two project teams becomes very simple and faster compared to manual looping.

4. Preventing Repeated Processing

When processing a bulk list, HashSet helps ensure that an item is processed only once. This prevents issues like double insertion, duplicate calculations, or repeated validations. It is useful in Excel uploads, log processing, or any batch system.

5. Cleaner and Maintainable Code

Using HashSet reduces the need for long “check-before-add” conditions. It results in cleaner, more readable, and less error-prone code. Whenever you need to ensure that values remain unique. such as roles, permissions, categories, or tags—HashSet is the most straightforward choice.

Conclusion

C# HashSet is a powerful collection designed to store only unique values, making it perfect for avoiding duplicates automatically. It offers very fast lookup and insert operations because it uses hashing internally. HashSet works best when we need to quickly check whether an item exists or not, rather than maintaining order. Overall, it helps improve performance while keeping our data clean, efficient, and duplicate-free.