Skip to content

Add an OrderedDictionary.TryAdd overload that returns the int-based index of an entry if the key already exists #107947

@eiriktsarpalis

Description

@eiriktsarpalis

Motivation

The CollectionsMarshal.GetValueRefOrAddDefault method for dictionaries provides a powerful mechanism for adding or updating a dictionary entry using only one lookup. The newly added OrderedDictionary<TKey, TValue> collection would similarly benefit from a such an API, however we don't need to make it as unsafe; simply knowing the int-based index of an entry makes it possible to very cheaply look up or update its value using the GetAt and SetAt methods, respectively.

API Proposal

namespace System.Collections.Generic;

public partial class OrderedDictionary<TKey, TValue>
{
    public bool TryAdd(TKey key, TValue value);
+   public bool TryAdd(TKey key, TValue value, out int index);
}

API Usage

See this conversation for a motivating use case.

Before

if (!dict.TryAdd(propertyName, value))
{
    int index = dict.IndexOf(propertyName); // Second lookup operation
    Debug.Assert(index >= 0);
    JsonNode? replacedValue = dict.GetAt(index).Value;
    DetachParent(replacedValue);
    dict.SetAt(index, value);
}

After

if (!dict.TryAdd(propertyName, value, out int index))
{
    JsonNode? replacedValue = dict.GetAt(index).Value;
    DetachParent(replacedValue);
    dict.SetAt(index, value);
}

Metadata

Metadata

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.Collectionsin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions