2010-12-16 93 views
3

如果我添加一个对象作为集合的关键,对象是否必须满足任何条件?我读了一篇关于不变性的文章,其中指出哈希表中的键是不可变的,因此这个问题。我用于收藏的钥匙是否需要满足任何要求?

感谢

+1

也许你想具体说明你所指的是哪种类型的键控集合... Dictionary 也许? – Reddog 2010-12-16 22:52:09

回答

4

的字典键可以是可变的,但改变它,而它存储在字典可能是一个非常糟糕的主意。如果密钥的哈希值发生变化,则根据密钥的新哈希值,字典条目可能位于错误的存储桶中。这意味着你将无法再找到它。从documentation of Dictionary

只要一个对象被用作Dictionary<TKey, TValue>的关键,它必须在不影响其散列值任何方式更改。根据字典的相等比较器,Dictionary<TKey, TValue>中的每个密钥必须是唯一的。一个密钥不能是null,但值可以是,如果值类型为TValue是一个引用类型。

0

基本上,一个键可以是任何对象,不能为空。出于安全原因,密钥应该是不可变的。

但是,你可以有:

Dictionary<Car, Color> 

Car不应该是可变的,你失去或改变它的点的标识(或哈希马克状态)。

0

我假设你正在使用类,而不是结构。结构的考虑因素不同。

答案是,“这取决于”。它取决于你的对象是否可以逻辑地称为“值类型” - 表示逻辑数据类型的逻辑值的东西 - 或者不是。 (这有点令人困惑,因为.NET文档将结构体称为“值类型”,我在更一般的OO定义中使用该术语 - 有些类实际上是值类型。)

值类型包括像字符串,日期,点等。在我们的代码中,我们有一个共同的值类型,它只是日期的月份和年份部分。值类型通常是不可变的。该值的标识基于其内容;如果它们具有相同的内容,则两个不同的实例在逻辑上是“相同的”。您可以有两个不同的字符串实例,但如果它们包含相同的字符序列,则它们是“相同”值。

另一方面,由于缺乏更好的术语,我将称之为“对象”:不代表逻辑值的事物。这些将是字符串构建器,文件流,阵列,客户,订单和产品等。这些不是具体的价值。该对象的身份是基于它的实例:两个不同的实例不是“相同的”;他们不同,因为他们是不同的实例。

因此,您的问题的答案取决于您的对象是否代表上述定义下的“值类型”或“对象”。

如果它们是“值类型”,那么您的班级需要覆盖EqualsGetHashCodeEquals应该返回true,如果两个实例是相同的类型并且具有相同的内容。GetHashCode应该返回值的内容的散列;如果两个实例“相同”,则它们必须返回相同的哈希码。

如果它们是“对象”,则从System.Object继承的EqualsGetHashCode实现将使用引用相等性来确定两个对象是否“相同”(并因此应该在对象中被视为相同的键)字典),这是你想要的。所以只要你不从继承的东西本身覆盖EqualsGetHashCode,你不需要做任何特殊的事情来使用“对象”作为关键。

相关问题