【问题标题】:Constructing immutable dictionary with inner immutable dictionary用内部不可变字典构造不可变字典
【发布时间】:2020-08-18 16:25:04
【问题描述】:

我有以下字典并希望使其不可变;

var dict = ConcurrentDictionary<Type, ConcurrentDictionary<Type, Action>>

然后我打电话

var immmutableDict = dict.ToImmutableDictionary();

但是,我相信这仍然会提供内部 ConcurrentDictionary&lt;Type, Action&gt; 字典。

如何使用现有函数以线程安全的方式制作整个字典的不可变副本,或者我是否需要锁定整个操作以确保原子转换?

ImmutableDictionary<Type, ImmutableDictionary<Type, Action>>

或者,如果上述方法不可行,我可以从一开始就重构代码以使用 ReadOnlyDictionary 字典,但是我面临与内部字典相同的挑战,以使其在构建期间只读:

var dict2 = new Dictionary<Type, Dictionary<Type, InstanceProducer>>();
/* snip perform adds to above dictionary to initialise state */

var immutableDict = dict2.ReadOnlyDictionary(); // ????
// where ReadOnlyDictionary<Type, ReadOnlyDictionary<Type, InstanceProducer>>(); is returned
// i need to make the above immutable with an immutable internal dictionary

【问题讨论】:

  • “线程安全时尚”和“原子转换”是什么意思?您的意思是希望生成的嵌套ImmutableDictionary 包含初始嵌套ConcurrentDictionary 的快照吗?如果你想要快照语义,那么获取它们的唯一方法是调用方法ConcurrentDictionary.ToArrayToImmutableDictionary 扩展方法在IEnumerable 接口上运行,因此它不会生成快照。生成的 ImmutableDictionary 可能包含在初始集合中从未共存的条目。

标签: c# .net concurrency immutable-collections


【解决方案1】:

您只需要将每个内部字典也转换为不可变字典,然后从中创建一个新的 ImmutableDictionary。

ImmutableDictionary<Type, ImmutableDictionary<Type, Action>> immutableDict = dict
    .ToImmutableDictionary(e => e.Key, e => e.Value.ToImmutableDictionary());

【讨论】:

    【解决方案2】:

    但是,我相信这仍然会提供内部 ConcurrentDictionary 字典。

    调用:

    var immmutableDict = dict.ToImmutableDictionary();
    

    将产生一个类型:ImutableDictionary&lt;Type, ConcurrentDictionary&lt;Type, Action&gt;,所以它不会是ConcurrentDictionary

    如何使用现有函数以线程安全的方式制作整个字典的不可变副本,或者我是否需要锁定整个操作以确保原子转换?

    要了解dict.ToImmutableDictionary() 的工作原理,请阅读官方文档,其中说:

    枚举一系列键/值对并生成其内容的不可变字典。

    这是线程安全的吗? 是的,因为ImmutableDictionary 是线程安全的,从ConcurrentDictionary 创建一个也应该是线程安全的。

    但是,值得再问自己一个问题:

    • 我为什么需要这个?

    这个问题的原因是Immutable这个词,意思是每次修改都会创建一个新的数据实例。

    考虑到多线程意味着多线程访问可能会更改数据(除非您知道它不会被更改),它可能会对性能造成很大影响。

    【讨论】:

    • 感谢 Arsen 的时间,我知道 ImutableDictionary&lt;Type, ConcurrentDictionary&lt;Type, Action&gt; 会被返回,但是这样内部的 ConcurrentDictionary 引用仍然是可修改的。这可能会变得非常混乱,然后我意识到使用 ReadOnly 字典的解决方法我只需要能够先初始化它然后“锁定”它,但内部字典也有同样的问题。
    • 我理解您的担忧。好吧,如果您有字典初始化部分的控件,我建议即使在初始化中也将ConcurrentDictionary 替换为ImutableDictionary,因为它们都是线程安全的,您不必担心这里的并发性。但是,如果您无权访问初始化部分,则必须遍历字典并逐项转换。
    猜你喜欢
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多