如何将 ConcurrentDictionary 转换为字典?

发布于 2024-10-05 16:46:06 字数 89 浏览 6 评论 0原文

我有一个 ConcurrentDictionary 对象,我想将其设置为 Dictionary 对象。

不允许在它们之间进行转换。那么我该怎么做呢?

I have a ConcurrentDictionary object that I would like to set to a Dictionary object.

Casting between them is not allowed. So how do I do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

冷情妓 2024-10-12 16:46:06

ConcurrentDictionary类实现 IDictionary接口,这应该足以满足大多数要求。但如果您确实需要一个具体的 Dictionary...

var newDictionary = yourConcurrentDictionary.ToDictionary(kvp => kvp.Key,
                                                          kvp => kvp.Value,
                                                          yourConcurrentDictionary.Comparer);

// or...
// substitute your actual key and value types in place of TKey and TValue
var newDictionary = new Dictionary<TKey, TValue>(yourConcurrentDictionary, yourConcurrentDictionary.Comparer);

The ConcurrentDictionary<K,V> class implements the IDictionary<K,V> interface, which should be enough for most requirements. But if you really need a concrete Dictionary<K,V>...

var newDictionary = yourConcurrentDictionary.ToDictionary(kvp => kvp.Key,
                                                          kvp => kvp.Value,
                                                          yourConcurrentDictionary.Comparer);

// or...
// substitute your actual key and value types in place of TKey and TValue
var newDictionary = new Dictionary<TKey, TValue>(yourConcurrentDictionary, yourConcurrentDictionary.Comparer);
故事未完 2024-10-12 16:46:06

为什么需要将其转换为字典? ConcurrentDictionary 实现了 IDictionary 接口,这还不够吗?

如果您确实需要一个Dictionary,您可以使用 LINQ复制它:

var myDictionary = myConcurrentDictionary.ToDictionary(entry => entry.Key,
                                                       entry => entry.Value);

请注意,这会复制。您不能只将ConcurrentDictionary 分配给Dictionary,因为ConcurrentDictionary 不是Dictionary 的子类型。这就是像 IDictionary 这样的接口的全部要点:您可以从具体实现(并发/非并发哈希映射)中抽象出所需的接口(“某种字典”)。

Why do you need to convert it to a Dictionary? ConcurrentDictionary<K, V> implements the IDictionary<K, V> interface, is that not enough?

If you really need a Dictionary<K, V>, you can copy it using LINQ:

var myDictionary = myConcurrentDictionary.ToDictionary(entry => entry.Key,
                                                       entry => entry.Value);

Note that this makes a copy. You cannot just assign a ConcurrentDictionary to a Dictionary, since ConcurrentDictionary is not a subtype of Dictionary. That's the whole point of interfaces like IDictionary: You can abstract away the desired interface ("some kind of dictionary") from the concrete implementation (concurrent/non-concurrent hashmap).

枯寂 2024-10-12 16:46:06

我想我已经找到了办法。

ConcurrentDictionary<int, int> concDict= new ConcurrentDictionary<int, int>( );
Dictionary dict= new Dictionary<int, int>( concDict);

I think i have found a way to do it.

ConcurrentDictionary<int, int> concDict= new ConcurrentDictionary<int, int>( );
Dictionary dict= new Dictionary<int, int>( concDict);
请持续率性 2024-10-12 16:46:06
ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>();
Dictionary<int,string> d = cd.ToDictionary(pair => pair.Key, pair => pair.Value);
ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>();
Dictionary<int,string> d = cd.ToDictionary(pair => pair.Key, pair => pair.Value);
深居我梦 2024-10-12 16:46:06

如果您只需要保证线程安全,而不需要保证即时快照,请使用concurrentDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);。

这是因为 .ToDictionary() 只是通过 IEnumerable 进行操作的 LINQ 实现。 ConcurrentDictionary 枚举器是线程安全的,但是当枚举器被枚举时,这些值可能会在您下面发生变化。

如果您需要保证即时快照,请使用concurrentDictionary.ToArray().ToDictionary(kvp => kvp.Key, kvp => kvp.Value);。

.ToArray()ConcurrentDictionary 本身实现,并使用内部锁来保证字典内容的即时快照。然后,您可以对结果数组执行任何您喜欢的操作,例如根据其值创建一个新字典。

If you only need to guarantee thread-safety, but not a moment-in-time snapshot, use concurrentDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);.

This is because .ToDictionary() is simply the LINQ implementation that operates over IEnumerable. The ConcurrentDictionary enumerator is thread-safe, but the values can change underneath you as the enumerator is enumerated.

If you need to guarantee a moment-in-time snapshot, use concurrentDictionary.ToArray().ToDictionary(kvp => kvp.Key, kvp => kvp.Value);.

.ToArray() is implemented by the ConcurrentDictionary itself, and uses an internal lock to guarantee a moment-in-time snapshot of the dictionary contents. You may then do whatever you like with the resultant array, such as creating a new dictionary from its values.

静水深流 2024-10-12 16:46:06

ConcurrentDictionary 转换为 Dictionary 有一些问题。

  1. 两个词典应具有相同的 比较器。否则有两把钥匙
    根据一个比较器而不同的值可能根据另一个比较器而相等,在这种情况下,尝试在目标字典中插入第二个键将导致运行时 ArgumentException 并显示消息 “已添加具有相同密钥的项目。”

  2. 尽管在实践中 ConcurrentDictionary 在枚举时发出唯一键文档,并且 Microsoft 工程师已明确指出观察到的行为 不是故意的。因此,没有什么可以阻止他们在未来的 .NET 版本中更改当前实现,从而允许在 ConcurrentDictionary 实例的单个枚举期间发出重复键。如果您使用具有 collectionDictionary 构造函数,这可能会再次导致运行时 ArgumentException 的出现字典参数。如果您想安全起见,最好采取防御措施,并使用 TryAdd 方法或设置 索引器TryAdd 将保留第一次出现的重复键,而 set 索引器将保留最后一次出现的重复键。

/// <summary>
/// Creates a Dictionary from a ConcurrentDictionary.
/// </summary>
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> source, bool snapshot = false)
{
    ArgumentNullException.ThrowIfNull(source);
    if (snapshot)
        return new Dictionary<TKey, TValue>(source.ToArray(), source.Comparer);

    // Create a Dictionary without snapshot semantics.
    Dictionary<TKey, TValue> result = new(source.Comparer);
    foreach (var (key, value) in source)
        result.TryAdd(key, value); // or result[key] = value;
    return result;
}

Converting a ConcurrentDictionary<K,V> to a Dictionary<K,V> has a couple of gotchas.

  1. The two dictionaries should have the same Comparer. Otherwise two keys
    that are different according to the one comparer might be equal according to the other comparer, in which case attempting to insert the second key in the target dictionary will cause a run-time ArgumentException with the message "An item with the same key has already been added."

  2. Although in practice a ConcurrentDictionary<K,V> emits unique keys when it is enumerated, this is not guaranteed by the documentation, and the Microsoft engineers have explicitly stated that the observed behavior is not intentional. So there is nothing that prevents them from changing the current implementation in a future .NET version, in a way that will allow the emission of duplicate keys during a single enumeration of a ConcurrentDictionary<K,V> instance. This could cause again the appearance of run-time ArgumentExceptions, if you use the Dictionary<K,V> constructor that has a collection or dictionary parameter. If you want to be on the safe side, it's a good idea to be defensive, and insert the key-value pairs in the Dictionary<K,V> with either the TryAdd method or the set indexer. The TryAdd will preserve the first occurrence of the duplicate key, while the set indexer will preserve the last.

/// <summary>
/// Creates a Dictionary from a ConcurrentDictionary.
/// </summary>
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> source, bool snapshot = false)
{
    ArgumentNullException.ThrowIfNull(source);
    if (snapshot)
        return new Dictionary<TKey, TValue>(source.ToArray(), source.Comparer);

    // Create a Dictionary without snapshot semantics.
    Dictionary<TKey, TValue> result = new(source.Comparer);
    foreach (var (key, value) in source)
        result.TryAdd(key, value); // or result[key] = value;
    return result;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文