.NET中真正不变的字典

Mig*_*uel 7 c# dictionary immutability

早上好,下午或晚上,

还是建立在我的问题关于不可变的字典在.NET中,我提出了以下问题:而如果再TKeyTValue是值类型,你可以做一个真正的字典不可改变的,在这个意义上,无论是它的内部结构也不值本身可以改变,如果这些参数是引用类型键,则可以轻松更改值,从而更改字典本身.我对吗?

非常感谢你.

Eri*_*ert 23

如果然后TKey和TValue是值类型,你可以使字典真正不可变,在某种意义上,它的内部结构和值本身都不能改变,如果这些参数是引用类型键和值可以很容易地改变,从而改变字典本身.我对吗?

不完全是.你已经确定了一个真正的问题,但你对它的描述还没有完全考虑过.

首先,我注意到,是的,在不可变字典中的值类型是不可变的,即使它是一个可变值类型.为什么?因为值类型只是通过改变包含它们的变量来改变.如果您的字典没有公开它用于存储值类型的变量,那么就无法更改这些变量.

但是,即使值类型本身是不可变的,不可变值类型也可以包含对可变引用类型的引用,现在我们遇到了同样的问题.将字典限制为值类型只会将问题推到某个级别,它无法解决问题!你真正需要保证"深层"不变性的是一个快速价值类型的字典."blittable"是指没有引用类型字段的值类型.(之所以这么称呼是因为您可以通过将这些位"直接"输出到磁盘来将其中一个序列化到存储中.)

遗憾的是,泛型类型系统中没有约束来约束blittable值类型.

现在让我们考虑不可变字典中可变引用类型的一般问题,无论这些引用类型是直接存在还是通过值类型的字段存在.如果引用类型在不可变字典中的带外变异,会出现什么问题?

好吧,首先想到的是,一个不可变的字典应该两次给同一个问题两次相同的答案,现在情况已经不再如此.如果您说"customers [name] .Address",您希望两次获得相同的答案,但如果客户是可以变异的引用类型,您将得到一个可能不同的答案.这可能是也可能不是可取的.(请注意,字典会给出相同的答案两次:它给客户对象提供相同的引用.实际上客户对象没有给出相同的答案两次.)

假设你没有尝试回忆可能改变的问题的答案,这通常不是一个大问题.

更大的问题是当哈希表中的对象作为键变异时,从而改变其哈希值并"丢失"表中的对象.

如果发生这种情况,那么有人不会遵守指南.指南是(1)引用类型应该尽可能不将其哈希码(和相等)基于可以变异的数据,以及(2)不应该改变用作哈希表中的键的对象.


Chr*_*Wue 2

结构是值类型,不一定是不可变的 - 所以答案是否定的。您可以设计不可变类型(使所有字段和属性只读)。但是,没有可用的类型约束(例如where TKey : class)可以让您强制执行它。

更新:一个例子:

class Bar { public int I; }
struct Foo { public Bar B; }

var b = new Bar();
var f = new Foo { B = b; }

dict[key] = f;
b.I++;
Run Code Online (Sandbox Code Playgroud)

我承认有点构造。