TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2625 2.39K
День 2174. #ЗаметкиНаПолях
Изучаем 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
  • 👍 28
More from @netdeveloperdiary
  1. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  2. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  3. Oct 3, 2026Post #3360
  4. Oct 3, 2026День 2803. #Оффтоп Чем Заняться, Пока Работают Агенты? У VS Code Есть Ответ Сейчас большую…
  5. Oct 2, 2026День 2802. #Карьера #Юмор Секреты Программирования, Известные Только Легендам Ещё один пос…
  6. Oct 1, 2026Post #3357
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →