据说C#规范将字符串设为不可变是为了避免哈希表在键引用更改字符串键内容时出现问题。
Dictionary<>类型允许使用引用类型作为键。字典如何避免导致“错位”值的修改键的问题?在使用对象作为键时是否进行成员逐一克隆?
据说C#规范将字符串设为不可变是为了避免哈希表在键引用更改字符串键内容时出现问题。
Dictionary<>类型允许使用引用类型作为键。字典如何避免导致“错位”值的修改键的问题?在使用对象作为键时是否进行成员逐一克隆?
Dictionary<TKey,TValue>
类型不会尝试防止用户修改使用的键。它完全取决于开发人员自己负责不改变键。Dictionary<TKey,TValue>
能够采取的唯一明智途径。考虑执行类似成员逐个克隆操作的影响。为了彻底,您需要进行深层克隆,因为键中引用的对象也可能被修改,从而影响哈希码。因此,现在表格中使用的每个键都必须克隆其完整的对象图以防止变异。这将是错误的,并且可能是非常昂贵的操作。如果您使用可变的引用类型作为键,则 GetHashCode()
的默认实现将保证哈希相等性,无论对象状态如何(即哈希值与引用相关,而不是与状态相关)。 但是,您是正确的,对于具有值相等语义的可变类型(其中GetHashCode
可能依赖于状态),将其用作字典键是不好的选择。
double
、Decimal
、List<T>.Enumerator
等),但大多数.NET中的类型都实现了Equals(Object)
以指示等价性;由于不同的可变类类型项永远不会等价,因此它们不应报告自己为Equals
(List<T>.Enumerator
的行为源于装箱和拆箱值类型具有不同的语义,但需要共享相同的Equals
方法)。 - supercatDictionary<>
类本身不会对可变键对象被更改进行保护。需要你自己知道你所使用的键类是否可变,并尽可能避免使用可变键类。
Dictionary<TKey, TValue>
中的键,就必须确保它不会以任何影响其哈希值的方式更改。每个键在 Dictionary<TKey, TValue>
中必须根据字典的相等比较器是唯一的。如果值类型 TValue
是引用类型,则键不能为 null
,但值可以为 null
。