Question
In C#, Dictionary<TKey, TValue> is often preferred over Hashtable, and similar guidance appears in many programming languages.
What are the main reasons for preferring a dictionary-style generic collection over a hashtable-style non-generic collection?
For example, how do these two compare?
using System;
using System.Collections;
using System.Collections.Generic;
class Example
{
static void Main()
{
Hashtable table = new Hashtable();
table[1] = "Alice";
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Alice";
}
}
Why is Dictionary<TKey, TValue> usually the better choice in modern C#?
Short Answer
By the end of this page, you will understand the difference between Hashtable and Dictionary<TKey, TValue> in C#, why generic collections are usually preferred, and when Hashtable might still appear in older code. You will also see how type safety, performance, readability, and maintainability make Dictionary the standard choice in modern C#.
Concept
Hashtable and Dictionary<TKey, TValue> both store data as key-value pairs. That means you use a key to quickly look up a value.
Example:
- Key:
1 - Value:
"Alice"
The main difference is that:
Hashtableis non-generic and stores keys and values asobjectDictionary<TKey, TValue>is generic and stores strongly typed keys and values
In modern C#, generic collections are usually preferred because they are safer and clearer.
Why this matters
1. Type safety
With Dictionary<int, string>, the compiler knows:
- keys must be
int - values must be
string
So this is allowed:
dict[1] = "Alice";
But this is rejected at compile time:
Mental Model
Think of Hashtable as a storage room where every box is labeled only as "object".
You can put anything into any box:
- numbers
- strings
- custom objects
That sounds flexible, but later you must open the box and figure out what is actually inside.
Dictionary<TKey, TValue> is more like a shelf with clear labels:
- key must be
int - value must be
string
Now every slot has a known shape. You cannot accidentally put the wrong thing there, and anyone reading the code understands the data immediately.
So:
Hashtable= flexible but vagueDictionary<TKey, TValue>= structured and safer
In real projects, structured usually wins.
Syntax and Examples
Core syntax
Hashtable
using System.Collections;
Hashtable table = new Hashtable();
table[1] = "Alice";
table[2] = "Bob";
string name = (string)table[1];
Notice the cast:
(string)table[1]
That is needed because the result is returned as object.
Dictionary<TKey, TValue>
using System.Collections.Generic;
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Alice";
dict[2] = "Bob";
string name = dict[1];
No cast is needed, because the dictionary already knows the value type is string.
Beginner-friendly example
Step by Step Execution
Consider this example:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Alice";
dict[2] = "Bob";
if (dict.TryGetValue(2, out string name))
{
Console.WriteLine(name);
}
}
}
Step by step
1. Create the dictionary
Dictionary<int, string> dict = new Dictionary<int, string>();
A new empty dictionary is created.
It will only accept:
intkeysstringvalues
2. Add the first item
Real World Use Cases
Key-value collections are used everywhere in software.
Common uses for Dictionary<TKey, TValue>
1. Caching data by ID
Dictionary<int, string> productNames = new Dictionary<int, string>();
Useful when you want fast lookup of a product name by product ID.
2. Counting occurrences
Dictionary<string, int> wordCounts = new Dictionary<string, int>();
Common in text analysis, logs, and reporting.
3. Mapping configuration values
Dictionary<string, string> config = new Dictionary<string, string>();
Used for application settings, headers, environment values, or query parameters.
4. Grouping application state
Dictionary<Guid, UserSession> sessions = new Dictionary<Guid, UserSession>();
Useful in web apps, game servers, or background services.
Real Codebase Usage
In real C# projects, developers usually choose Dictionary<TKey, TValue> because it works well with modern coding patterns.
Common patterns
Guarded lookup with TryGetValue
if (!users.TryGetValue(userId, out var user))
{
return "User not found";
}
return user.Name;
This avoids exceptions and makes missing data explicit.
Validation before insert
if (string.IsNullOrWhiteSpace(email))
{
throw new ArgumentException("Email is required.");
}
emailToUserId[email] = userId;
Counting pattern
if (counts.ContainsKey(word))
{
counts[word]++;
}
else
{
counts[word] = 1;
}
Or more compactly:
counts[word] = counts.GetValueOrDefault(word) + 1;
Configuration lookup
Common Mistakes
1. Using direct indexing when the key may not exist
Broken example:
Dictionary<int, string> users = new Dictionary<int, string>();
string name = users[5];
This throws a KeyNotFoundException if key 5 is missing.
Better:
if (users.TryGetValue(5, out string name))
{
Console.WriteLine(name);
}
2. Choosing Hashtable for new code without a reason
Broken example:
Hashtable table = new Hashtable();
table[1] = "Alice";
table[2] = 99;
This compiles, but now values have inconsistent types.
Better:
Dictionary<int, string> users = new Dictionary<, >();
users[] = ;
Comparisons
Dictionary<TKey, TValue> vs Hashtable
| Feature | Dictionary<TKey, TValue> | Hashtable |
|---|---|---|
| Generic | Yes | No |
| Type safety | Compile-time | Mostly runtime |
| Needs casting | No, usually | Yes, often |
| Boxing/unboxing for value types | Avoided | Can happen |
| Readability | High | Lower |
| Modern C# usage | Preferred | Mostly legacy |
| Works with strongly typed APIs | Very well | Less naturally |
Cheat Sheet
Quick answer
Prefer Dictionary<TKey, TValue> over Hashtable in modern C# because it is:
- strongly typed
- safer at compile time
- usually faster for typed data
- easier to read and maintain
Syntax
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "Alice";
string name = dict[1];
Hashtable table = new Hashtable();
table[1] = "Alice";
string name = (string)table[1];
Main reasons to prefer Dictionary
- No repeated casting
- Better IntelliSense
- Fewer runtime type errors
- Avoids boxing/unboxing for value types
- Clear key and value types in the code
Safe lookup
if (dict.TryGetValue(1, out name))
{
Console.WriteLine(name);
}
FAQ
Is Dictionary faster than Hashtable in C#?
Often yes, especially when value types are involved, because Dictionary<TKey, TValue> avoids boxing and unboxing and uses strong typing.
Why does Hashtable require casting?
Because it stores values as object. When you read a value, you usually need to convert it back to the expected type.
Is Hashtable obsolete in C#?
Not completely, but it is generally considered a legacy-style collection for most modern code. Dictionary<TKey, TValue> is usually preferred.
When should I still use Hashtable?
Mostly when working with old code or APIs that specifically require non-generic collections.
What is the biggest advantage of Dictionary<TKey, TValue>?
Type safety. The compiler checks that keys and values are the correct types before the program runs.
Can Dictionary replace Hashtable in most code?
Yes, in most new C# code it is the better default choice.
Are both based on hash lookup ideas?
Yes. Both are hash-based key-value collections designed for fast lookup by key.
Mini Project
Description
Build a small word counter that reads a sentence and counts how many times each word appears. This demonstrates why Dictionary<string, int> is a practical choice: each word maps clearly to a numeric count, and the compiler keeps the types consistent.
Goal
Create a console program that counts repeated words using Dictionary<string, int> and prints the results.
Requirements
- Ask the user to enter a sentence
- Split the sentence into words
- Count how many times each word appears
- Store the counts in a
Dictionary<string, int> - Print each word with its total count
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.