我来自一个python世界,其中只有可以删除的对象可以用作字典的键。 C#中是否有类似的限制?你可以使用自定义类型作为字典键吗?
答案 0 :(得分:6)
字典密钥的要求是它具有可比性和可清除性。这是整个.NET中的乌龟,每种类型(除了指针类型)都派生自System.Object,并且由于它的Equals()方法,它总是可比较的。并且感谢它的GetHashCode()方法。因此,任何.NET类型都可以自动用作密钥。
如果您想使用自己的类型作为键,那么只需要重新定义对象标识即可。换句话说,如果您需要两个不同对象的能力相等。然后,您将覆盖Equals()方法,通常比较对象的字段。然后你还必须覆盖GetHashCode(),相等的对象必须生成相同的哈希码。
如果无法更改类型或者您想要自定义行为,尤其是对于Dictionary,那么您可以传递自定义IEqualityComparer<>到构造函数。请记住,使用自己的GetHashCode()生成的哈希码的质量决定了字典的效率。
答案 1 :(得分:2)
是的,你可以,只需实现IEqualityComparer接口,覆盖GetHashCode和Equals。
答案 2 :(得分:1)
是的,密钥的重要之处在于它们实现(或具有良好的默认实现)GetHashCode
和Equals
。 Dictionary<T, K>
实施可以利用通用IEqualityComparer<T>
。
所有自定义类型都会附带GetHashCode
和Equals
的默认实现,因为它们是object
的成员,但是,默认情况可能并不总是与您的类型相关。
字典首先尝试获取哈希码以确定值将进入的存储桶。如果存在哈希冲突,则它会回落到相等位置(我认为)。
请注意,您使用的密钥类型(class
,struct
,原始类型等)可以产生不同的性能特征。在我们的代码库中,我们发现GetHashCode
中struct
的默认实现并不像我们自己覆盖它那么快。我们还发现嵌套字典在访问时间方面比具有复合键的单个字典表现更好。