Skip to content

[API Proposal]: 'ConcurrentDictionary<TKey, TValue>.AlternateLookup<TAlternateKey>.GetOrAdd' overloads #112974

@Sergio0694

Description

@Sergio0694

Background and motivation

The alternate lookup for ConcurrentDictionary<TKey, TValue> is missing the GetOrAdd overloads, which makes it necessary to do a wasteful secondary lookup to try to get a value and add it if not present. We need to do this in several startup paths in CsWinRT, meaning that without a GetOrAdd we'd end up hitting the second lookup for basically every single marshalled type requiring dynamic type checks at startup:

public static Type Get(ReadOnlySpan<char> runtimeClassName)
{
    var alternate = TypeNameToMappedTypes.GetAlternateLookup<ReadOnlySpan<char>>();

    if (alternate.TryGetValue(runtimeClassName, out Type? type))
    {
        return type;
    }

    type = typeof(int); // Get the value from somewhere

    if (alternate.TryAdd(runtimeClassName, type))
    {
        return type;
    }

    return alternate[runtimeClassName];
}

The code is also very verbose and clunky, on top of being inefficient.

API Proposal

 namespace System.Collections.Concurrent;

 partial class ConcurrentDictionary<TKey, TValue>
 {
     partial struct AlternateLookup<TAlternateKey>
     {
+       public TValue GetOrAdd(TAlternateKey key, Func<TAlternateKey, TValue> valueFactory);
+       public TValue GetOrAdd<TArg>(TAlternateKey key, Func<TAlternateKey, TArg, TValue> valueFactory, TArg factoryArgument) where TArg : allows ref struct;
+       public TValue GetOrAdd(TAlternateKey key, TValue value);
     }
 }

API Usage

The above snippet can then become just this:

public static Type Get(ReadOnlySpan<char> runtimeClassName)
{
    var alternate = TypeNameToMappedTypes.GetAlternateLookup<ReadOnlySpan<char>>();

    return alternate.GetOrAdd(runtimeClassName, GetTypeFromRuntimeClassName);
}

Way simpler, and with no repeated lookups and unnecessary overhead.

Risks

None, these APIs already exist and are well established on ConcurrentDictionary<TKey, TValue> itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.Collectionspartner-impactThis issue impacts a partner who needs to be kept updated

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions