Есть ли способ поменять ключ и значение в Concurrent Dictionary на С#? Я знаю, что для типа Dictionary
это может быть что-то вроде
dictionary = dictionary.ToDictionary(x => x.Value, x => x.Key);
Что-нибудь подобное в ConcurrentDictionary
?
Есть ли способ поменять ключ и значение в Concurrent Dictionary на С#? Я знаю, что для типа Dictionary
это может быть что-то вроде
dictionary = dictionary.ToDictionary(x => x.Value, x => x.Key);
Что-нибудь подобное в ConcurrentDictionary
?
Вы не можете преобразовать или преобразовать Dictionary в ConcurrentDictionary напрямую. Купить вы можете создать ConcurrentDictionary со словарем, проверьте этот конструктор
public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection);
И посмотрите метод расширения LINQ, который вы говорите
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector);
Итак, если Dictionary
совместим с IEnumerable<KeyValuePair<TKey, TValue>>
Решение 1
Просто используйте метод расширения ToDictionary LINQ
var concurrentDict = new ConcurrentDictionary<string, string>();
/* Add some items */
bool firstItem = concurrentDict.TryAdd("1", "First"); //returns true
bool secondItem = concurrentDict.TryAdd("2", "Second"); //returns true
/* Swaping Value <-> Key to new Dictionary */
Dictionary<string,string> normalDict = concurrentDict.ToDictionary(x => x.Value, x => x.Key);
/* creating ConcurrentDictionary */
var newConcurrentDict = new ConcurrentDictionary<string, string>(normalDict);
Решение 2
Как насчет потокобезопасности?
Вы можете использовать собственный метод расширения (например, LINQ)
var concurrentDict = new ConcurrentDictionary<string, string>();
/* Add some items */
bool firstItem = concurrentDict.TryAdd("1", "First"); //returns true
bool secondItem = concurrentDict.TryAdd("2", "Second"); //returns true
/* Swaping Value <-> Key to new Dictionary */
Dictionary<string,string> normalDict = concurrentDict.ToDictionary(x => x.Value, x => x.Key);
/* creating ConcurrentDictionary */
var newConcurrentDict = normalDict.ToConcurrentDictionary();
Метод расширения
Ссылка https://stackoverflow.com/a/27064366/1669574
public static class ConcurrentDictionaryExtensions
{
public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer)
{
if (source == null) throw new ArgumentNullException("source");
if (keySelector == null) throw new ArgumentNullException("keySelector");
if (elementSelector == null) throw new ArgumentNullException("elementSelector");
ConcurrentDictionary<TKey, TElement> d = new ConcurrentDictionary<TKey, TElement>(comparer);
foreach (TSource element in source)
d.TryAdd(keySelector(element), elementSelector(element));
return d;
}
public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return ToConcurrentDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance,
null);
}
public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
return ToConcurrentDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance,
comparer);
}
public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
{
return ToConcurrentDictionary<TSource, TKey, TElement>(source, keySelector, elementSelector, null);
}
internal class IdentityFunction<TElement>
{
public static Func<TElement, TElement> Instance
{
get { return x => x; }
}
}
}
ConcurrentDictionary
, — это блокирует операции добавления/удаления/доступа. А из coruse MT только штучки, вроде TryAdd и TryUpdate - тоже с блокировками. - person Christopher   schedule 16.11.2019ConcurrentDictionary
активно обновляется несколькими потоками? Если да, то вы, вероятно, захотите сделать снимок данных, содержащихся вConcurrentDictionary
, перед выполнением свопа, а не использовать сочетание новых и старых записей. Чтобы сделать снимок, вам нужно использовать его методToArray
. Не используйте методы LINQ (ссылка). - person Theodor Zoulias   schedule 16.11.2019ConcurrentDictionary
. Другие параллельные контейнеры, напримерConcurrentQueue
, можно безопасно использовать с LINQ, поскольку их методGetEnumerator
использует моментальный снимок данных. (цитирование ) - person Theodor Zoulias   schedule 16.11.2019