Table of Contents

DefaultingDictionary<TKey, TValue> Class

Definition

Namespace
Bodu.Collections.Generic
Assembly
Bodu.Collections.dll
Package
Bodu.Collections 1.0.0
Source
DefaultingDictionary{T,T}.IDictionary.cs

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

TKey

Specifies the type of keys in the dictionary.

TValue

Specifies the type of values in the dictionary.

Inheritance
DefaultingDictionary<TKey, TValue>
Implements
IDictionary<TKey, TValue>
ICollection<KeyValuePair<TKey, TValue>>
IReadOnlyDictionary<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

valueFactory Func<TKey, TValue>

The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.

Exceptions

ArgumentNullException

valueFactory is 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

valueFactory Func<TKey, TValue>

The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.

comparer IEqualityComparer<TKey>

The equality comparer to use for keys, or null to use the default comparer.

Exceptions

ArgumentNullException

valueFactory is 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

valueFactory Func<TKey, TValue>

The delegate invoked to produce the value for a key read through the indexer while absent. Must not be null.

capacity int

The initial number of entries the inner dictionary can hold without resizing.

comparer IEqualityComparer<TKey>

The equality comparer to use for keys, or null to use the default comparer.

Exceptions

ArgumentNullException

valueFactory is null.

ArgumentOutOfRangeException

capacity is 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

key TKey

The 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

key is null.

KeyNotFoundException

The property is retrieved and key is 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

item KeyValuePair<TKey, TValue>

The key/value pair to add to the dictionary.

Exceptions

ArgumentNullException

item.Key is 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

key TKey

The key of the element to add. Must not be null.

value TValue

The value to associate with key.

Exceptions

ArgumentNullException

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

item KeyValuePair<TKey, TValue>

The object to locate in the ICollection<T>.

Returns

bool

true if item is 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

key TKey

The 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

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

array KeyValuePair<TKey, TValue>[]

The one-dimensional Array that is the destination of the elements copied from ICollection<T>. The Array must have zero-based indexing.

arrayIndex int

The zero-based index in array at which copying begins.

Exceptions

ArgumentNullException

array is null.

ArgumentOutOfRangeException

arrayIndex is less than 0.

ArgumentException

The number of elements in the source ICollection<T> is greater than the available space from arrayIndex to the end of the destination array.

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

item KeyValuePair<TKey, TValue>

The object to remove from the ICollection<T>.

Returns

bool

true if item was successfully removed from the ICollection<T>; otherwise, false. This method also returns false if item is 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

key TKey

The key of the entry to remove. Must not be null.

Returns

bool

true if an actually-stored entry was found and removed; otherwise, false.

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

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

key TKey

The key of the value to retrieve. Must not be null.

value TValue

When 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

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

ProductVersions
.NET8, 10