I know about Dictionary<K,V>.TryAdd() method added in .NET Core 2.0 that improves performance by checking only once if the dictionary contains the key before adding the element unlike in:
if(!dico.ContainsKey(key)) { dico.Add(key,val); } // .Add() calls ContainsKey() a second time
However for performance reason I'd like to lazy build val only if !dico.ContainsKey(key):
if(!dico.ContainsKey(key)) { dico.Add(key, new Value()); }
In this situation TryAdd() degrades performance since the value is not lazy built.
dico.TryAdd(key,new Value());
Is there a way to both have a single ContainsKey() call AND lazy build the value? Something like AddWithNoContainsKeyCheck():
if(!dico.ContainsKey(key)) { dico.AddWithNoContainsKeyCheck(key, new Value()); }
Yes, it is possible, by using the advanced API
CollectionsMarshal.GetValueRefOrAddDefault, available from .NET 6 and later:The
CollectionsMarshal.GetValueRefOrAddDefaultreturns a reference to the value stored in the dictionary. In case thevalueFactoryfails, it is important to remove the newly added key. Otherwise a key with adefault(TValue)will be inadvertently added in the dictionary.Note: The extension method
TryAddin this answer offers the same functionality with the more convenient and more fluentGetOrAdd. Theboolreturn value (conveying the information if the value was created or already existed) is rarely needed in practice.