我来自Python的世界,在那里只有可哈希对象才可以用作字典的键。在C#中是否存在类似的限制?你能使用自定义类型作为字典的键吗?
我来自Python的世界,在那里只有可哈希对象才可以用作字典的键。在C#中是否存在类似的限制?你能使用自定义类型作为字典的键吗?
字典键的要求是可以比较和可哈希。在.NET中,每种类型(除了指针类型)都派生自System.Object并且由于其Equals()方法始终可比较,所以它总是可比较的。而其GetHashCode()方法也使其可哈希。所以任何.NET类型都可以自动用作键。
如果你想使用自己的类型作为键,则只需要在需要重新定义对象标识时执行一些特殊操作。换句话说,如果你需要让两个不同的对象相等,则需要重写Equals()方法,通常比较对象的字段。然后还必须重写GetHashCode(),使相等的对象生成相同的哈希码。
如果该类型无法更改或您想为Dictionary自定义行为,则可以将自定义的IEqualityComparer<>传递给构造函数。请记住,使用自己的GetHashCode()生成的哈希码的质量决定了字典的效率。
GetHashCode
和Equals
。 Dictionary<T, K>
实现可以利用通用的 IEqualityComparer<T>
。GetHashCode
和Equals
的默认实现,因为它们是object
的成员,但这个默认值可能并不总是与您的类型相关。class
、struct
、基本类型等)可能会产生不同的性能特征。在我们的代码库中,我们发现struct
中的默认GetHashCode
实现不如我们自己重写的快。我们还发现,嵌套字典在访问时间方面表现更好,而单个具有复合键的字典则较差。class
类型,其默认的相等性实现方式并非基于字段相等,而是基于引用相等。对于一个 struct
类型,我想它是基于值相等,前 x 个字节块或类似的某些奥秘进行比较的。个人认为,确保自定义类型作为键的实现方式被明确定义是很重要的,但同时我们很少使用自定义类型作为键。 - Adam Houldsworth可以,只需要实现 IEqualityComparer 接口,重写 GetHashCode 和 Equals 方法。
System.Object
有一个默认的GetHashCode()实现,它可能只是基于对象的地址(或者在垃圾回收的情况下可能是一种ID)。其他一些对象,例如System.String
,则覆盖它以返回与它们的内容相关的内容。对于所有其他情况,您可以使用IEqualityComparer
的实现来自定义哈希处理。例如,查看StringComparer
类:其每个成员都具有不同的IEqualityComparer
实现,以匹配字符串比较,因此您可以实现区分大小写的哈希处理。 - Medinoc