提问人:Rabadash8820 提问时间:9/25/2016 更新时间:9/25/2016 访问量:655
为什么要对引用类型使用值相等 [重复]
Why Use Value Equality On a Reference Type [duplicate]
问:
这篇 MSDN 文章阐明了何时将类型声明为值类型 (struct) 与引用类型 (class)。特别是,它说:
除非该类型具有以下所有特征,否则请避免定义结构:
- 它在逻辑上表示单个值,类似于原始类型(int、double 等)。
- 它的实例大小小于 16 字节。
- 它是不可变的。
- 它不必经常装箱。
在所有其他情况下,应将类型定义为类。
然后,这篇 MSDN 文章阐明了在类型上重写 Object.Equals() 的一些准则,包括:
当一个类型是不可变的时,...重载运算符 == 来比较值相等而不是引用相等可能很有用,因为作为不可变对象,只要它们具有相同的值,就可以认为它们是相同的。在非不可变类型中覆盖运算符 == 不是一个好主意。
所以在我看来,如果一个类型是不可变的,你只需将其声明为结构并覆盖 ValueType.Equals()。但是,如果你的类型被声明为类,那么理论上你只需要引用语义。这篇 SO 帖子似乎支持这一点。所以我的问题是,你为什么要费心在引用类型上覆盖 Equals()?这样做就像说引用语义对于你的引用类型来说不够好,这对我来说毫无意义。我能想到的唯一例子是,如果你有一个大型(>16 字节实例)类,它混合了可变和不可变字段,但即便如此,你似乎只需要引用语义。
答:
对于您的具体问题 - “您为什么要在引用类型上重写 Equals()?”:如果您希望其他 .NET 方法将类的两个实例视为相等,即使它们不是同一个实例,也可以重写 Equals()。
考虑。通过重写,可以确保该方法提供正确的结果,即使被比较的特定类实例实际上不是同一个实例。List<T>.Contains()
Equals()
我自己在WPF中经常遇到这种情况。我遇到过这样一种情况,即某些控件(特别是)具有我的对象的副本,这些副本与我测试它们的实例不同。这使得像 和属性这样的方法无法正常工作,直到我覆盖了该类。我能想到一个肯定会发生这种情况的特定示例:假设您有一个类,其中包含作为数据库查询结果创建的实例列表。用该结果集填充 。稍后,您从另一个数据库查询(也许是某种筛选器)中获得了一个新结果集,现在想要选择第二个查询结果中的所有项目。如果不覆盖 ,则无法设置 ,因为 中的实例将与第二个查询中的实例不同。正如评论中指出的那样,还有其他方法可以解决这个问题,但在我看来,覆盖提供了最干净的解决方案。ListBox
ScrollIntoView
SelectedItem
Equals
Person
ListBox
ListBox
Equals
SelectedItems
ListBox
Equals
这只是一个例子。我相信你很快就会遇到其他人。
评论
coll.Where(x => x.ID == someItemID)
评论
string