ILookup interface vs IDictionary
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
ILookup and IDictionary both map keys to values, but they solve different problems in .NET. Choosing the wrong one usually leads to extra code, poor readability, or unnecessary allocations. This guide compares their behavior, performance tradeoffs, and the situations where each type is the better fit.
Core Topic Sections
Core semantic difference
IDictionary maps one key to one value. If you assign a key again, the previous value is replaced unless you prevent it.
ILookup maps one key to many values. Each key returns a sequence, even if only one element exists.
This single difference changes API design:
- Dictionary is ideal for mutable key-value state.
- Lookup is ideal for grouped read-only query results.
Mutability and lifecycle
Dictionary is mutable. You can add, update, and remove entries after creation.
Lookup is effectively immutable from consumer code. Most lookups are created through LINQ ToLookup, then treated as a query result snapshot.
Mutable and immutable collection behavior should follow your workflow:
- Ongoing updates, use dictionary.
- Group once and read many times, use lookup.
Basic dictionary usage
Dictionary gives direct key access and fast updates, which is useful in caches and request-scoped accumulators.
Basic lookup usage
Lookup indexing is convenient because missing keys return an empty sequence instead of throwing an exception.
Missing key behavior matters
Dictionary index access for a missing key throws. You often need TryGetValue to stay safe.
Lookup index access for a missing key returns an empty enumerable. That makes query pipelines simpler because you can iterate without defensive checks.
This behavior is often the deciding factor in reporting and analytics code where sparse keys are normal.
Performance considerations
Dictionary lookup is usually very fast for single-value retrieval and updates. It is the right choice for hot code paths that mutate state.
Lookup has upfront grouping cost when calling ToLookup, but retrieval by key is efficient afterward. It performs well when the grouped result is reused many times.
If you only need one grouped pass, GroupBy might be enough. If you repeatedly query by key, materializing a lookup usually pays off.
API design guidance
Use dictionary in service code when your object owns mutable state. Use lookup at boundaries where you return grouped read-only data.
A practical pattern is:
- Ingest mutable events into dictionary-based structures.
- Publish query-friendly grouped projections as lookup or immutable DTO collections.
This separates write concerns from read concerns and reduces accidental mutation.
Converting between the two
Sometimes you need both representations:
- Dictionary to lookup: project values then call
ToLookup. - Lookup to dictionary: aggregate each grouping to one representative value.
When converting lookup to dictionary, define how to collapse multiple values per key. Common options are first value, last value, sum, or custom merge rule.
Common Pitfalls
- Using dictionary when a key naturally has multiple values and then storing lists manually.
- Using lookup for mutable workflows and fighting its read-only design.
- Accessing dictionary index directly on uncertain keys and triggering exceptions.
- Building lookup repeatedly in loops instead of creating it once and reusing it.
- Converting grouped data to dictionary without defining deterministic merge rules.
Summary
IDictionaryis one key to one mutable value.ILookupis one key to many read-only values.- Dictionary is best for mutable state and direct updates.
- Lookup is best for grouped query results and sparse-key reads.
- Choose based on mutation needs, missing-key behavior, and reuse pattern.

