2

我想将两个类的实例存储在字典结构中,并使用 IEquatable 来确定这些实例的唯一性。这两个类共享一个(抽象)基类。考虑以下类:

abstract class Foo
{
   ...
}

class SubFoo1 : Foo
{
   ...
}

class SubFoo2 : Foo
{
   ...
}

字典将被删除:Dictionary<Foo, Bar>

哪些类应该声明为 IEquatable?那些声明的泛型类型 T 应该是什么?这甚至可能吗?

4

5 回答 5

4

不要将任何东西声明为IEquatable<T>. 正如 Marc 所说,在继承和平等方面,这通常是一个问题。

相反,为这个特定字典中的键计算出你想要什么样的相等性,并实现IEqualityComparer<Foo>,然后将其传递给字典构造函数。

通常,如何比较特定情况下的密钥是相当清楚的。

于 2010-04-22T21:26:23.750 回答
0

这取决于你的课程代表什么。因此,没有“通用”解决方案。如果有,那么System.Object将实现,因为无论如何IEquatable<object>都继承自。object所以你可以问同样的问题,Object而不是Foo.

长话短说,这取决于你想用你的类层次结构实现什么。

长话短说,我同意很难确定什么使对象相等,因为即使对于相同的对象类型,也可能有不同的要求。当您使用缓存时,相等性将由对象的实体 ID 确定。当您使用 Do-/Undo-List 时,您需要另一个限定符,因为列表中每个对象的 ID 可能相同。

我想我离题了一点,但我希望我能给你一些有用的观点。;-)

于 2010-04-22T21:16:17.670 回答
0

当您开始获得继承时,选择T. 基本类型是显而易见的选择,但我想知道是否只覆盖Equalsand是否更合适GetHashCode

您可能还得出结论,这样复杂的场景可能不是键的错误选择,而是使用更简单、更可预测的键。特别是您希望“哈希”基于类型的某些不可变方面,并且“哈希”和“等于”必须兼容。如果类型不是,这些细微差别很难保证sealed

于 2010-04-22T21:20:25.297 回答
0

您始终可以在字典构造函数中指定自己的相等比较器。如果你不这样做,字典会IEquatable<TKey>在你的情况下寻找,IEquatable<Foo>因此你应该实现那个。

于 2010-04-22T21:26:38.450 回答
0

可继承的类几乎不应该实现IEquatable<T>。对于任何类型T,实现的每个对象都IEquatable<T>应该这样做,以使 的语义与 的语义相IEquatable<T>.Equals匹配Object.Equals。如果一个类实现IEquatable<Foo>了一些Foo并且派生类改变了语义Object.Equals但没有重新实现IEquatable<Foo>.Equals,那么后者的语义匹配前者的唯一方法是接口实现简单地调用虚拟Object.Equals本身;如果接口只是将其参数传递给Object.Equals,则实现它没有任何好处。

于 2012-06-13T00:16:51.100 回答