如何将 ConcurrentDictionary 转换为字典?
我有一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
ConcurrentDictionary
类实现IDictionary
接口,这应该足以满足大多数要求。但如果您确实需要一个具体的Dictionary
...The
ConcurrentDictionary<K,V>
class implements theIDictionary<K,V>
interface, which should be enough for most requirements. But if you really need a concreteDictionary<K,V>
...为什么需要将其转换为字典?
ConcurrentDictionary
实现了IDictionary
接口,这还不够吗?如果您确实需要一个
Dictionary
,您可以使用 LINQ复制它:请注意,这会复制。您不能只将ConcurrentDictionary 分配给Dictionary,因为ConcurrentDictionary 不是Dictionary 的子类型。这就是像 IDictionary 这样的接口的全部要点:您可以从具体实现(并发/非并发哈希映射)中抽象出所需的接口(“某种字典”)。
Why do you need to convert it to a Dictionary?
ConcurrentDictionary<K, V>
implements theIDictionary<K, V>
interface, is that not enough?If you really need a
Dictionary<K, V>
, you can copy it using LINQ: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).
我想我已经找到了办法。
I think i have found a way to do it.
如果您只需要保证线程安全,而不需要保证即时快照,请使用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. TheConcurrentDictionary
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 theConcurrentDictionary
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.将
ConcurrentDictionary
转换为Dictionary
有一些问题。两个词典应具有相同的
比较器
。否则有两把钥匙根据一个比较器而不同的值可能根据另一个比较器而相等,在这种情况下,尝试在目标字典中插入第二个键将导致运行时
ArgumentException
并显示消息 “已添加具有相同密钥的项目。”尽管在实践中
ConcurrentDictionary
在枚举时发出唯一键,文档,并且 Microsoft 工程师已明确指出观察到的行为 不是故意的。因此,没有什么可以阻止他们在未来的 .NET 版本中更改当前实现,从而允许在ConcurrentDictionary
实例的单个枚举期间发出重复键。如果您使用具有collection
的Dictionary
构造函数,这可能会再次导致运行时ArgumentException
的出现字典
参数。如果您想安全起见,最好采取防御措施,并使用TryAdd
方法或设置
索引器。TryAdd
将保留第一次出现的重复键,而set
索引器将保留最后一次出现的重复键。Converting a
ConcurrentDictionary<K,V>
to aDictionary<K,V>
has a couple of gotchas.The two dictionaries should have the same
Comparer
. Otherwise two keysthat 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."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 aConcurrentDictionary<K,V>
instance. This could cause again the appearance of run-timeArgumentException
s, if you use theDictionary<K,V>
constructor that has acollection
ordictionary
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 theDictionary<K,V>
with either theTryAdd
method or theset
indexer. TheTryAdd
will preserve the first occurrence of the duplicate key, while theset
indexer will preserve the last.