DefaultingDictionary<TKey, TValue> Class
Definition
Represents a dictionary whose indexer getter materializes missing entries on demand: reading an absent key invokes a value factory, stores the produced value, and returns it.
public sealed class DefaultingDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable where TKey : notnull
Type Parameters
TKeySpecifies the type of keys in the dictionary.
TValueSpecifies the type of values in the dictionary.
- Inheritance
-
DefaultingDictionary<TKey, TValue>
- Implements
-
IDictionary<TKey, TValue>ICollection<KeyValuePair<TKey, TValue>>IReadOnlyDictionary<TKey, TValue>IReadOnlyCollection<KeyValuePair<TKey, TValue>>IEnumerable<KeyValuePair<TKey, TValue>>
- Inherited Members
- Extension Methods
Remarks
DefaultingDictionary<TKey, TValue> is the .NET analogue of Python's collections.defaultdict:
the ValueFactory delegate fixed at construction plays the role of default_factory, and -
exactly as in Python, where __missing__ fires only for d[key] - only the indexer getter
materializes defaults. TryGetValue(TKey, out TValue), ContainsKey(TKey),
Remove(TKey), Count, and enumeration observe only entries that have actually been
stored; none of them invoke the factory.
This differs from the GetOrAdd extension methods on
IDictionary<TKey, TValue> in Bodu.Core, which stay the lightweight
per-call-site option: there the factory is supplied at each call, whereas here the default-producing policy is baked
into the dictionary itself so every plain indexer read applies it.
Reentrancy contract: when the factory itself mutates the dictionary - including adding an entry for the very key
being materialized - the stored result is always the factory's return value. Any value the factory assigned
to that key during its own execution is overwritten before the indexer returns. This keeps the contract
deterministic: dictionary[key] on a miss always stores and returns what the factory returned.
TValue is unconstrained, so a factory returning null for a reference or
nullable value type stores null as-is; the key is then present with a null
value and the factory is not invoked for it again.
DefaultingDictionary<TKey, TValue> is not thread-safe. The indexer's check-invoke-store sequence is not atomic; concurrent access requires external synchronization.
var groups = new DefaultingDictionary<string, List<int>>(_ => new List<int>());
groups["odd"].Add(1); // miss - the factory creates the list, it is stored, then mutated
groups["odd"].Add(3); // hit - the stored list is returned; the factory is not invoked
bool has = groups.ContainsKey("even"); // false - lookups never materialize defaults
int count = groups["odd"].Count; // 2
Constructors
DefaultingDictionary(Func<TKey, TValue>)
Initializes a new instance of the DefaultingDictionary<TKey, TValue> class that is empty, uses the specified value factory, and uses the default key comparer.
public DefaultingDictionary(Func<TKey, TValue> valueFactory)
Parameters
valueFactoryFunc<TKey, TValue>The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.
Exceptions
- ArgumentNullException
valueFactoryis null.
DefaultingDictionary(Func<TKey, TValue>, IEqualityComparer<TKey>?)
Initializes a new instance of the DefaultingDictionary<TKey, TValue> class that is empty, uses the specified value factory, and uses the specified key comparer.
public DefaultingDictionary(Func<TKey, TValue> valueFactory, IEqualityComparer<TKey>? comparer)
Parameters
valueFactoryFunc<TKey, TValue>The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.
comparerIEqualityComparer<TKey>The equality comparer to use for keys, or null to use the default comparer.
Exceptions
- ArgumentNullException
valueFactoryis null.
DefaultingDictionary(Func<TKey, TValue>, int, IEqualityComparer<TKey>?)
Initializes a new instance of the DefaultingDictionary<TKey, TValue> class that is empty, uses the specified value factory, and has the specified initial capacity and key comparer.
public DefaultingDictionary(Func<TKey, TValue> valueFactory, int capacity, IEqualityComparer<TKey>? comparer)
Parameters
valueFactoryFunc<TKey, TValue>The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.
capacityintThe initial number of entries the inner dictionary can hold without resizing.
comparerIEqualityComparer<TKey>The equality comparer to use for keys, or null to use the default comparer.
Exceptions
- ArgumentNullException
valueFactoryis null.- ArgumentOutOfRangeException
capacityis less than zero.
Properties
Comparer
Gets the IEqualityComparer<T> used to determine key equality.
public IEqualityComparer<TKey> Comparer { get; }
Property Value
- IEqualityComparer<TKey>
The comparer used for key identity in the inner dictionary.
Count
Gets the number of elements contained in the ICollection<T>.
public int Count { get; }
Property Value
- int
The number of elements contained in the ICollection<T>.
Remarks
Counts only actually-stored entries; reading the count never materializes defaults.
IsReadOnly
Gets a value indicating whether the ICollection<T> is read-only.
public bool IsReadOnly { get; }
Property Value
- bool
true if the ICollection<T> is read-only; otherwise, false.
this[TKey]
Gets or sets the element with the specified key.
public TValue this[TKey key] { get; set; }
Parameters
keyTKeyThe key of the element to get or set.
Property Value
- TValue
The element with the specified key.
Remarks
The getter never throws KeyNotFoundException: when the key is absent it invokes ValueFactory, stores the produced value, and returns it. When the key is present the stored value is returned and the factory is not invoked. Only this getter materializes defaults - every other read surface observes stored entries only.
If the factory mutates the dictionary - including assigning the very key being materialized - the factory's return value is stored last and wins; see the reentrancy contract in the type-level remarks.
Exceptions
- ArgumentNullException
keyis null.- KeyNotFoundException
The property is retrieved and
keyis not found.- NotSupportedException
The property is set and the IDictionary<TKey, TValue> is read-only.
Keys
Gets an ICollection<T> containing the keys of the IDictionary<TKey, TValue>.
public ICollection<TKey> Keys { get; }
Property Value
- ICollection<TKey>
An ICollection<T> containing the keys of the object that implements IDictionary<TKey, TValue>.
Remarks
Returns the inner dictionary's live key collection over the actually-stored entries. The collection is read-only through this surface.
ValueFactory
Gets the delegate invoked by the indexer getter to produce the value for a missing key.
public Func<TKey, TValue> ValueFactory { get; }
Property Value
- Func<TKey, TValue>
The value factory fixed at construction.
Values
Gets an ICollection<T> containing the values in the IDictionary<TKey, TValue>.
public ICollection<TValue> Values { get; }
Property Value
- ICollection<TValue>
An ICollection<T> containing the values in the object that implements IDictionary<TKey, TValue>.
Remarks
Returns the inner dictionary's live value collection over the actually-stored entries. The collection is read-only through this surface.
Methods
Add(KeyValuePair<TKey, TValue>)
Adds the specified key/value pair to the dictionary.
public void Add(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The key/value pair to add to the dictionary.
Exceptions
- ArgumentNullException
item.Keyis null.- ArgumentException
An element with the same key already exists in the dictionary.
Add(TKey, TValue)
Adds the specified key and value to the dictionary.
public void Add(TKey key, TValue value)
Parameters
keyTKeyThe key of the element to add. Must not be null.
valueTValueThe value to associate with
key.
Exceptions
- ArgumentNullException
keyis null.- ArgumentException
An element with the same key already exists in the dictionary.
Clear()
Removes all entries from the dictionary.
public void Clear()
Contains(KeyValuePair<TKey, TValue>)
Determines whether the ICollection<T> contains a specific value.
public bool Contains(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The object to locate in the ICollection<T>.
Returns
- bool
true if
itemis found in the ICollection<T>; otherwise, false.
Remarks
Matches only actually-stored pairs; the lookup never materializes defaults. Value equality is determined by Default.
ContainsKey(TKey)
Determines whether the IDictionary<TKey, TValue> contains an element with the specified key.
public bool ContainsKey(TKey key)
Parameters
keyTKeyThe key to locate in the IDictionary<TKey, TValue>.
Returns
- bool
true if the IDictionary<TKey, TValue> contains an element with the key; otherwise, false.
Remarks
Returns true only for actually-stored keys; the lookup never materializes defaults.
Exceptions
- ArgumentNullException
keyis null.
CopyTo(KeyValuePair<TKey, TValue>[], int)
Copies the elements of the ICollection<T> to an Array, starting at a particular Array index.
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
Parameters
arrayKeyValuePair<TKey, TValue>[]The one-dimensional Array that is the destination of the elements copied from ICollection<T>. The Array must have zero-based indexing.
arrayIndexintThe zero-based index in
arrayat which copying begins.
Exceptions
- ArgumentNullException
arrayis null.- ArgumentOutOfRangeException
arrayIndexis less than 0.- ArgumentException
The number of elements in the source ICollection<T> is greater than the available space from
arrayIndexto the end of the destinationarray.
GetEnumerator()
Returns an enumerator that iterates through the collection.
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
Returns
- IEnumerator<KeyValuePair<TKey, TValue>>
An enumerator that can be used to iterate through the collection.
Remarks
Enumerates only actually-stored entries in the inner dictionary's unspecified, insertion-biased order; enumeration never materializes defaults. Enumerator invalidation matches Dictionary<TKey, TValue>.
Remove(KeyValuePair<TKey, TValue>)
Removes the first occurrence of a specific object from the ICollection<T>.
public bool Remove(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The object to remove from the ICollection<T>.
Returns
- bool
true if
itemwas successfully removed from the ICollection<T>; otherwise, false. This method also returns false ifitemis not found in the original ICollection<T>.
Exceptions
- NotSupportedException
The ICollection<T> is read-only.
Remove(TKey)
Removes the entry with the specified key from the dictionary.
public bool Remove(TKey key)
Parameters
keyTKeyThe key of the entry to remove. Must not be null.
Returns
Remarks
Removal never materializes defaults: removing an absent key simply returns false, and a subsequent indexer read of that key invokes the factory again.
Exceptions
- ArgumentNullException
keyis null.
TryGetValue(TKey, out TValue)
Attempts to retrieve the value associated with the specified key without materializing a default.
public bool TryGetValue(TKey key, out TValue value)
Parameters
keyTKeyThe key of the value to retrieve. Must not be null.
valueTValueWhen this method returns, contains the stored value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter.
Returns
- bool
true if the dictionary contains an actually-stored entry with the specified key; otherwise, false.
Remarks
Unlike the indexer getter, this method never invokes ValueFactory - a missing key reports
false and stores nothing, matching Python's defaultdict.get.
Exceptions
- ArgumentNullException
keyis null.
Explicit Interface Implementations
IReadOnlyDictionary<TKey, TValue>.Keys
Gets an enumerable collection that contains the keys in the read-only dictionary.
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys { get; }
Returns
- IEnumerable<TKey>
An enumerable collection that contains the keys in the read-only dictionary.
IReadOnlyDictionary<TKey, TValue>.Values
Gets an enumerable collection that contains the values in the read-only dictionary.
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values { get; }
Returns
- IEnumerable<TValue>
An enumerable collection that contains the values in the read-only dictionary.
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 |