ILookup interface vs IDictionary
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
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.
Related reading
- Immutable array in Java
- Immutable queue in Clojure
- ImmutableSortedDictionary range enumeration by key
- Implement a queue in which push_rear, pop_front and get_min are all constant time operations
- I'm lost. What happened to ASP.NET MVC 5?
- Image vs Bitmap class
- implement Broadcast Tree on OMNET++
- Implement Stack using Two Queues

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.