Table of Contents

MultiValueDictionary<TKey, TValue> Class

Definition

Namespace
Bodu.Collections.Generic
Assembly
Bodu.Collections.dll
Package
Bodu.Collections 1.0.0
Source
MultiValueDictionary{T,T}.IEnumerable.cs

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

TKey

The type of keys.

TValue

The 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

backing MultiValueBacking

The backing that controls how values are stored per key.

Exceptions

ArgumentOutOfRangeException

Thrown when backing is 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

backing MultiValueBacking

The backing that controls how values are stored per key.

keyComparer IEqualityComparer<TKey>

The equality comparer used to compare keys.

Exceptions

ArgumentOutOfRangeException

Thrown when backing is 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

backing MultiValueBacking

The backing that controls how values are stored per key.

keyComparer IEqualityComparer<TKey>

The equality comparer used to compare keys.

valueComparer IEqualityComparer<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 backing is 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

comparer IEqualityComparer<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

key TKey

The 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 key is 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

key TKey

The key to add the value under.

value TValue

The 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 key is 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

key TKey

The key to add the values under.

values IEnumerable<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 key or values is 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

key TKey

The key to locate.

Returns

bool

true if key exists; otherwise, false.

Exceptions

ArgumentNullException

Thrown when key is null.

ContainsValue(TKey, TValue)

Determines whether value is associated with key.

public bool ContainsValue(TKey key, TValue value)

Parameters

key TKey

The key to search under.

value TValue

The value to locate.

Returns

bool

true if the value is found under the key; otherwise, false.

Remarks

Under Set backing, values are matched using ValueComparer; under List backing, the default equality comparer for TValue is used.

Exceptions

ArgumentNullException

Thrown when key is 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

key TKey

The key whose values are returned.

Returns

IReadOnlyList<TValue>

A live read-only list of values in insertion order.

Exceptions

ArgumentNullException

Thrown when key is null.

KeyNotFoundException

Thrown when key does 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

key TKey

The key under which to remove the value.

value TValue

The value to remove.

Returns

bool

true if a value was removed; otherwise, false.

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 key is null.

RemoveAll(TKey)

Removes key and all of its associated values from the dictionary.

public bool RemoveAll(TKey key)

Parameters

key TKey

The key to remove.

Returns

bool

true if key was found and removed; otherwise, false.

Exceptions

ArgumentNullException

Thrown when key is null.

TryGetValues(TKey, out IReadOnlyList<TValue>)

Attempts to return the values associated with key.

public bool TryGetValues(TKey key, out IReadOnlyList<TValue> values)

Parameters

key TKey

The key whose values are returned.

values IReadOnlyList<TValue>

The values associated with key when the key exists.

Returns

bool

true if key exists; otherwise, false.

Exceptions

ArgumentNullException

Thrown when key is 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

int

The number of distinct keys, equivalent to KeyCount.

Remarks

The dictionary's enumeration yields one entry per key, so this matches KeyCount rather than the total value count exposed by the public Count property.

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

ProductVersions
.NET8, 10