MultiValueDictionary<TKey, TValue> Class
Definition
Represents a mutable dictionary that maps each key to zero or more values.
public sealed class MultiValueDictionary<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, IReadOnlyList<TValue>>>, IEnumerable<KeyValuePair<TKey, IReadOnlyList<TValue>>>, IEnumerable where TKey : notnull
Type Parameters
TKeyThe type of keys.
TValueThe type of values associated with each key.
- Inheritance
-
MultiValueDictionary<TKey, TValue>
- Implements
- Inherited Members
- Extension Methods
Examples
// Multiple values under a single key - values are retained in insertion order.
var map = new MultiValueDictionary<string, int>();
map.Add("odd", 1);
map.Add("odd", 3);
map.Add("even", 2);
Console.WriteLine(map.Count); // 3 - total key-value entries
Console.WriteLine(map.KeyCount); // 2 - distinct keys
// The indexer returns a live read-only view; absent keys yield an empty list rather than throwing.
foreach (int value in map["odd"])
Console.WriteLine(value);
// Flatten into one KeyValuePair per stored value.
foreach (KeyValuePair<string, int> pair in map.Flatten())
Console.WriteLine($"{pair.Key}: {pair.Value}");
Remarks
MultiValueDictionary<TKey, TValue> is a mutable one-to-many map, sometimes referred to as a multimap. A single key can have multiple associated values, and values for the same key are retained in insertion order.
The value storage is selected at construction through MultiValueBacking and reported by Backing. The default, List, is a list multimap: every added value is retained, including per-key duplicates. Set is an order-preserving set multimap: values are deduplicated per key using ValueComparer, and the insertion order of each value's first occurrence is preserved. Under Set backing, each add performs a linear scan of the key's existing values - a trade-off that keeps the values ordered and preserves the IReadOnlyList<T> view contract.
The Count property returns the total number of key-value entries across all keys. Use KeyCount to obtain the number of distinct keys currently held.
The indexer returns the values for a key when the key is present, or an empty read-only list when the key is absent. Use GetValues(TKey) when absence should be treated as an error, or TryGetValues(TKey, out IReadOnlyList<TValue>) when absence should be handled without throwing.
Values returned by the indexer, GetValues(TKey), TryGetValues(TKey, out IReadOnlyList<TValue>), and enumeration are live read-only views. They reflect later dictionary changes for the same key, but they do not expose the mutable backing List<T> used internally.
Enumerators are invalidated by structural modification. Adding values, removing values, removing keys, or clearing the dictionary after enumeration begins causes the next enumeration step to throw InvalidOperationException. Operations that do not change the dictionary, such as removing a missing key or adding an empty range, do not invalidate existing enumerators.
The dictionary's regular enumeration yields one entry per distinct key, where each entry contains the key and its associated read-only value list. Use Flatten() to enumerate one KeyValuePair<TKey, TValue> per stored value.
This type is not thread-safe. Concurrent reads and writes require external synchronization.
Constructors
MultiValueDictionary()
Initializes a new instance of the MultiValueDictionary<TKey, TValue> class that is empty and uses the default equality comparer for keys.
public MultiValueDictionary()
MultiValueDictionary(MultiValueBacking)
Initializes a new instance of the MultiValueDictionary<TKey, TValue> class that is empty, uses the specified value backing, and uses the default equality comparers for keys and values.
public MultiValueDictionary(MultiValueBacking backing)
Parameters
backingMultiValueBackingThe backing that controls how values are stored per key.
Exceptions
- ArgumentOutOfRangeException
Thrown when
backingis not a defined MultiValueBacking value.
MultiValueDictionary(MultiValueBacking, IEqualityComparer<TKey>?)
Initializes a new instance of the MultiValueDictionary<TKey, TValue> class that is empty, uses the specified value backing and key comparer, and uses the default equality comparer for values.
public MultiValueDictionary(MultiValueBacking backing, IEqualityComparer<TKey>? keyComparer)
Parameters
backingMultiValueBackingThe backing that controls how values are stored per key.
keyComparerIEqualityComparer<TKey>The equality comparer used to compare keys.
Exceptions
- ArgumentOutOfRangeException
Thrown when
backingis not a defined MultiValueBacking value.
MultiValueDictionary(MultiValueBacking, IEqualityComparer<TKey>?, IEqualityComparer<TValue>?)
Initializes a new instance of the MultiValueDictionary<TKey, TValue> class that is empty and uses the specified value backing, key comparer, and value comparer.
public MultiValueDictionary(MultiValueBacking backing, IEqualityComparer<TKey>? keyComparer, IEqualityComparer<TValue>? valueComparer)
Parameters
backingMultiValueBackingThe backing that controls how values are stored per key.
keyComparerIEqualityComparer<TKey>The equality comparer used to compare keys.
valueComparerIEqualityComparer<TValue>The equality comparer used to compare values.
Remarks
The backing and value comparer are immutable after construction. The value comparer is consulted only under Set backing; under List backing it is stored and reported by ValueComparer but value operations use the default equality comparer.
Exceptions
- ArgumentOutOfRangeException
Thrown when
backingis not a defined MultiValueBacking value.
MultiValueDictionary(IEqualityComparer<TKey>?)
Initializes a new instance of the MultiValueDictionary<TKey, TValue> class that is empty and uses the specified equality comparer for keys.
public MultiValueDictionary(IEqualityComparer<TKey>? comparer)
Parameters
comparerIEqualityComparer<TKey>The equality comparer used to compare keys.
Properties
Backing
Gets the backing that controls how values are stored per key.
public MultiValueBacking Backing { get; }
Property Value
- MultiValueBacking
The MultiValueBacking value selected at construction.
Comparer
Gets the equality comparer used to determine equality of keys.
public IEqualityComparer<TKey> Comparer { get; }
Property Value
- IEqualityComparer<TKey>
The IEqualityComparer<T> instance used to compare keys.
Count
Gets the total number of key-value entries stored across all keys.
public int Count { get; }
Property Value
- int
The total number of values, summed across all keys.
this[TKey]
Gets the values associated with key as a read-only list.
public IReadOnlyList<TValue> this[TKey key] { get; }
Parameters
keyTKeyThe key whose values are retrieved.
Property Value
- IReadOnlyList<TValue>
A live read-only list of values associated with
key, or an empty list when the key is absent.
Remarks
The returned list reflects later changes made through the dictionary, but it does not expose the mutable backing list.
Exceptions
- ArgumentNullException
Thrown when
keyis null.
KeyCount
Gets the number of distinct keys currently held in the dictionary.
public int KeyCount { get; }
Property Value
- int
The number of distinct keys.
Keys
Gets a read-only view of all keys in the dictionary.
public IReadOnlyCollection<TKey> Keys { get; }
Property Value
- IReadOnlyCollection<TKey>
A collection containing all distinct keys.
ValueComparer
Gets the equality comparer used to determine equality of values.
public IEqualityComparer<TValue> ValueComparer { get; }
Property Value
- IEqualityComparer<TValue>
The IEqualityComparer<T> instance supplied at construction, or the default comparer.
Remarks
The comparer is consulted only under Set backing, where it drives duplicate suppression in Add(TKey, TValue) and AddRange(TKey, IEnumerable<TValue>) and value matching in Remove(TKey, TValue) and ContainsValue(TKey, TValue). Under List backing the property still reports the construction value, but value operations use the default equality comparer.
Methods
Add(TKey, TValue)
Appends value to the values associated with key.
public void Add(TKey key, TValue value)
Parameters
keyTKeyThe key to add the value under.
valueTValueThe value to append.
Remarks
Under Set backing, a value already associated with key
according to ValueComparer is ignored: the dictionary is left unchanged and active enumerators
remain valid. Under List backing, every value is appended, including
duplicates.
Exceptions
- ArgumentNullException
Thrown when
keyis null.
AddRange(TKey, IEnumerable<TValue>)
Appends each element of values to the values associated with key.
public void AddRange(TKey key, IEnumerable<TValue> values)
Parameters
keyTKeyThe key to add the values under.
valuesIEnumerable<TValue>The values to append.
Remarks
The operation is atomic with respect to this dictionary. If the source sequence throws while being enumerated, the dictionary is left unchanged. An empty source is treated as a no-op and does not invalidate active enumerators.
Under Set backing, values already associated with key
according to ValueComparer are skipped, and duplicates within values itself
collapse to their first occurrence. A source whose values are all duplicates is treated as a no-op and does not
invalidate active enumerators.
Exceptions
- ArgumentNullException
Thrown when
keyorvaluesis null.
Clear()
Removes all keys and their associated values from the dictionary.
public void Clear()
Remarks
Each removed bucket's value list is cleared so that any outstanding read-only views previously handed out by GetValues(TKey), TryGetValues(TKey, out IReadOnlyList<TValue>), or the indexer reflect the removal.
ContainsKey(TKey)
Determines whether key has at least one value.
public bool ContainsKey(TKey key)
Parameters
keyTKeyThe key to locate.
Returns
Exceptions
- ArgumentNullException
Thrown when
keyis null.
ContainsValue(TKey, TValue)
Determines whether value is associated with key.
public bool ContainsValue(TKey key, TValue value)
Parameters
keyTKeyThe key to search under.
valueTValueThe value to locate.
Returns
Remarks
Under Set backing, values are matched using ValueComparer; under
List backing, the default equality comparer for TValue
is used.
Exceptions
- ArgumentNullException
Thrown when
keyis null.
Flatten()
Returns a flat sequence of all key-value pairs, one pair per value entry across all keys.
public IEnumerable<KeyValuePair<TKey, TValue>> Flatten()
Returns
- IEnumerable<KeyValuePair<TKey, TValue>>
An enumerable in which each item represents one value for one key.
Remarks
The order of keys is not guaranteed. Values within a key appear in insertion order.
Exceptions
- InvalidOperationException
Thrown when the dictionary is modified after enumeration begins.
GetEnumerator()
Returns an enumerator that iterates the key-value-list pairs in the dictionary.
public MultiValueDictionary<TKey, TValue>.Enumerator GetEnumerator()
Returns
- MultiValueDictionary<TKey, TValue>.Enumerator
An MultiValueDictionary<TKey, TValue>.Enumerator for the dictionary.
Remarks
The enumerator captures a structural-version token at creation. Any subsequent structural modification invalidates the enumerator. The next call to MoveNext() or Reset() throws InvalidOperationException.
GetValues(TKey)
Returns the values associated with key as a read-only list.
public IReadOnlyList<TValue> GetValues(TKey key)
Parameters
keyTKeyThe key whose values are returned.
Returns
- IReadOnlyList<TValue>
A live read-only list of values in insertion order.
Exceptions
- ArgumentNullException
Thrown when
keyis null.- KeyNotFoundException
Thrown when
keydoes not exist in the dictionary.
Remove(TKey, TValue)
Removes one occurrence of value from the values associated with key.
public bool Remove(TKey key, TValue value)
Parameters
keyTKeyThe key under which to remove the value.
valueTValueThe value to remove.
Returns
Remarks
Under Set backing, the value to remove is matched using
ValueComparer; under List backing, the default equality comparer
for TValue is used.
Exceptions
- ArgumentNullException
Thrown when
keyis null.
RemoveAll(TKey)
Removes key and all of its associated values from the dictionary.
public bool RemoveAll(TKey key)
Parameters
keyTKeyThe key to remove.
Returns
Exceptions
- ArgumentNullException
Thrown when
keyis null.
TryGetValues(TKey, out IReadOnlyList<TValue>)
Attempts to return the values associated with key.
public bool TryGetValues(TKey key, out IReadOnlyList<TValue> values)
Parameters
keyTKeyThe key whose values are returned.
valuesIReadOnlyList<TValue>The values associated with
keywhen the key exists.
Returns
Exceptions
- ArgumentNullException
Thrown when
keyis null.
Explicit Interface Implementations
IEnumerable<KeyValuePair<TKey, IReadOnlyList<TValue>>>.GetEnumerator()
Returns an enumerator that iterates through the collection.
IEnumerator<KeyValuePair<TKey, IReadOnlyList<TValue>>> IEnumerable<KeyValuePair<TKey, IReadOnlyList<TValue>>>.GetEnumerator()
Returns
- IEnumerator<KeyValuePair<TKey, IReadOnlyList<TValue>>>
An enumerator that can be used to iterate through the collection.
IReadOnlyCollection<KeyValuePair<TKey, IReadOnlyList<TValue>>>.Count
Gets the number of elements yielded by the dictionary's enumeration, which equals the number of distinct keys.
int IReadOnlyCollection<KeyValuePair<TKey, IReadOnlyList<TValue>>>.Count { get; }
Returns
Remarks
IEnumerable.GetEnumerator()
Returns an enumerator that iterates through a collection.
IEnumerator IEnumerable.GetEnumerator()
Returns
- IEnumerator
An IEnumerator object that can be used to iterate through the collection.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |