Description
Background and motivation
ConditionalWeakTable<TKey, TValue>
has a Remove
method that internally also retrieves the removed item, if present, but does not surface it. There is no existing method on it that allows removing an item while also getting the removed item, if present. This makes it unnecessarily expensive to opportunistically remove items while also doing something with them (eg. removing them from some other data structure).
Eg. we hit this in the Windows Community Toolkit (CommunityToolkit/Windows#569):
if (_debounceInstances.TryGetValue(timer, out Action? action))
{
_debounceInstances.Remove(timer); // Repeated lookup 🙁
action.Invoke();
}
It would be nice to just be able to do this with a single API, which would be simpler to read and also more efficient:
if (_debounceInstances.Remove(timer, out Action? action))
{
action.Invoke();
}
The new API would also make the whole operation atomic, which is also nice to have and might be necessary in some scenarios.
Implementing the new API is trivial, as ConditionalWeakTable<TKey, TValue>
already has the necessary logic, just not exposed.
API Proposal
namespace System.Runtime.CompilerServices;
public sealed class ConditionalWeakTable<TKey, TValue>
{
public bool Remove(TKey key);
+ public bool Remove(TKey key, [MaybeNullWhen(false)] out TValue value);
}
API Usage
Updating the example above to use the new API:
if (_debounceInstances.Remove(timer, out Action? action))
{
action.Invoke();
}
Alternative Designs
Keep using TryGetValue
+ Remove
, and waste an extra lookup. Also the whole thing is not atomic. And it's clunkier.
Risks
None, it's just a new convenience API with a well known signature also used on lots of other similar data structures.