Изучаем CollectionsMarshal на Примере Словарей
Небезопасный класс CollectionsMarshal предоставляет набор методов для эффективного доступа к базовым представлениям данных коллекций. Обратите внимание на слово «небезопасный». Хотя представленные методы и эффективны, неосторожное обращение может нарушить целостность данных. Сегодня рассмотрим, как использовать CollectionsMarshal для эффективной работы со словарями.
В отличие от ConcurrentDictionary, Dictionary не имеет метода GetOrAdd. Этот метод полезен, когда вы хотите добавить пару ключ-значение в словарь, если ключ не существует, или вернуть значение, если ключ уже существует. Наивная реализация:
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dict,
TKey key,
TValue value)
where TKey : notnull
{
if (dict.TryGetValue(key, out var result))
return result;
dict[key] = value;
return value;
}
Проблема в том, что к словарю обращаются дважды: один раз для проверки существования ключа и один раз для добавления пары ключ-значение. Это означает, что вы дважды вычисляете хэш ключа и вызываете метод Equals как минимум дважды, что неэффективно.
Метод CollectionsMarshal.GetValueRefOrAddDefault возвращает ссылку на значение, связанное с ключом, и логическое значение, указывающее, существует ли ключ. Поскольку метод возвращает ссылку, вы можете обновить значение:
public static TValue GetOrAdd<TKey, TValue>(
this Dictionary<TKey, TValue> dict,
TKey key,
TValue value)
where TKey : notnull
{
ref var dictVal = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out var exists);
if (exists)
return dictVal;
dictVal = value;
return value;
}
Другой полезны метод, GetValueRefOrNullRef, позволяет, например, обновлять значение по ключу, если оно существует:
public static bool TryUpdate<TKey, TValue>(
this Dictionary<TKey, TValue> dict,
TKey key,
TValue value)
where TKey : notnull
{
ref var dictVal = ref CollectionsMarshal.GetValueRefOrNullRef(dict, key);
if (!Unsafe.IsNullRef(ref dictVal))
{
dictVal = value;
return true;
}
return false;
}
Источник: https://www.meziantou.net/exploring-collectionsmarshal-for-dictionary.htm