Codectionary / Developer documentation / C#

HashSet<T>

HashSet<T> is a collection that stores unique elements with no guaranteed ordering, backed by a hash table. Adding a duplicate element has no effect, since HashSet automatically enforces uniqueness. It provides very fast average-case performance for adding, removing, and checking membership, and offers built-in set operations like union, intersection, and difference.

Read the syntax

HashSet<T> stores distinct values and supports membership tests. Add returns false when an equal value already exists; it does not add another copy.

UnionWith, IntersectWith and ExceptWith mutate the receiving set. A hash set is not a sorted sequence, so sort before display when output order matters.

Syntax

HashSet<Type> set = new HashSet<Type>();

Examples

Creating a HashSet and Adding Elements

Duplicates are automatically ignored.

HashSet<string> tags = new HashSet<string>();
tags.Add("csharp");
tags.Add("dotnet");
tags.Add("csharp");  // duplicate - ignored, Add() returns false

Console.WriteLine(string.Join(", ", tags));  // csharp, dotnet
Console.WriteLine(tags.Count);                // 2
  1. Duplicates are automatically ignored.
  2. HashSet<T> stores distinct values and supports membership tests. Add returns false when an equal value already exists; it does not add another copy.
  3. The repeated csharp Add is ignored, leaving Count at 2. The joined values show both unique tags, but their order should not be relied upon.

Checking Membership

HashSet provides very fast membership testing, much faster than searching a List<T>.

HashSet<int> validIds = new HashSet<int> { 101, 102, 103 };

Console.WriteLine(validIds.Contains(102));  // true
Console.WriteLine(validIds.Contains(999));  // false
  1. HashSet provides very fast membership testing, much faster than searching a List<T>.
  2. HashSet<T> stores distinct values and supports membership tests. Add returns false when an equal value already exists; it does not add another copy.
  3. Contains finds 102 and does not find 999. This expresses membership without manually looping over the IDs.

Set Operations

Union, intersection, and difference using built-in methods.

HashSet<int> a = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> b = new HashSet<int> { 3, 4, 5, 6 };

HashSet<int> union = new HashSet<int>(a);
union.UnionWith(b);
Console.WriteLine(string.Join(", ", union));  // 1, 2, 3, 4, 5, 6

HashSet<int> intersection = new HashSet<int>(a);
intersection.IntersectWith(b);
Console.WriteLine(string.Join(", ", intersection));  // 3, 4

HashSet<int> difference = new HashSet<int>(a);
difference.ExceptWith(b);
Console.WriteLine(string.Join(", ", difference));  // 1, 2
  1. Union, intersection, and difference using built-in methods.
  2. HashSet<T> stores distinct values and supports membership tests. Add returns false when an equal value already exists; it does not add another copy.
  3. Copies protect the original a set while each operation changes its own result. Union holds 1–6, intersection holds 3 and 4, and difference holds 1 and 2; display order is unspecified.

Removing Duplicates from a List

A very common practical use of HashSet<T>.

List<string> namesWithDupes = new List<string> { "John", "Zain", "John", "Jamal" };

HashSet<string> uniqueNames = new HashSet<string>(namesWithDupes);
Console.WriteLine(string.Join(", ", uniqueNames));  // John, Zain, Jamal
  1. A very common practical use of HashSet<T>.
  2. HashSet<T> stores distinct values and supports membership tests. Add returns false when an equal value already exists; it does not add another copy.
  3. Constructing a set from the list discards the second John. It holds three distinct names, but a HashSet does not promise to preserve the source order.

Best practices

  • Use HashSet<T> when you need fast membership testing (Contains()) or automatic deduplication and do not care about element order
  • Use a SortedSet<T> instead if you need elements kept in sorted order, since HashSet makes no ordering guarantee
  • Always override Equals() and GetHashCode() properly (or use a record) for any custom class stored in a HashSet, or duplicate detection will not work correctly
  • Prefer a HashSet<T> over a List<T> for repeated Contains() checks on large collections - it is dramatically faster

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading