List.Contains 返回 false,即使它看起来应该返回 true
Posted
技术标签:
【中文标题】List.Contains 返回 false,即使它看起来应该返回 true【英文标题】:List.Contains returns false, even though it seems it should return true 【发布时间】:2011-01-18 00:36:37 【问题描述】:Sub pageload() Handles Me.Load
Dim bom As New List(Of Car)
Dim car1 As New Car With .Name = "Pea", .Year = 2
Dim car2 As New Car With .Name = "Pea", .Year = 2
bom.Add(car1)
MsgBox(bom.Contains(car2))
End Sub
为什么???我的意思是对象具有完全相同的数据,为什么它说它不包含?
【问题讨论】:
你有两辆车。两者恰好是相同的颜色和型号。第一个在名单上,第二个不在。非常简单。 那么 GetHashCode 呢?它也不一样。它实际上是做什么的? 确实如此。您正在将Car
视为值类型。从“现实世界”的角度来考虑(毕竟,OOP 就是在现实世界对象之后建模数据):如果我开着红色丰田凯美瑞开车到你家,然后在离开时闯入 你的 红色丰田凯美瑞开回家,我是不是开着我来的那辆车离开的?
【参考方案1】:
Contains
方法通过对对象调用 Equals
方法来测试相等性。除非您重写 Car
类中的 Equals
方法并实现自己的比较方法,否则 Car
的实例将通过 引用身份 被视为相等(完全相同的对象)不是基于它们的内容相等。
你创建的那些对象肯定不是同一个对象。证明:改变一个不会改变另一个。
【讨论】:
【参考方案2】:关键是car
是引用类型,而不是值类型。您创建的两个汽车对象是完全不同的东西。每个都指向内存中的不同位置,即使它们碰巧具有所有相同的属性。把他们想象成同卵双胞胎。一个人上了一辆卡车。如果您问另一个是否在卡车上,答案是否定的,即使在某种意义上他们完全相同。
如果您定义了car2
,然后将其设置为等于car1 (Dim car2 As New Car = car1
),那么您将不得不指向内存中完全相同的位置。你的结果会是真的。两个变量都会引用同一个汽车对象。
现在,如果这是一个值类型,如整数或日期(或结构。字符串也是如此),那么任何相同的值都将被视为相同.你把 10 美元放在车里,我问车里有没有 10 美元。答案是肯定的,不管是我的 10 美元还是你的 10 美元。
您的示例很好地说明了引用类型和值类型的行为方式的关键差异。
默认情况下,对于引用类型,Equals 属性检查两个对象是否是对内存中完全相同位置的引用,而不是所有值是否相同。 (Contains 使用 Equals 属性。)如果您愿意,您可以覆盖特定对象的该行为。
【讨论】:
【参考方案3】:你的两辆车是完全独立的。
Contains
检查是否有任何列表项与您提供的参数一样指向同一个对象。而不是这两个对象在逻辑上是否相等。
如果你想让它这样做,你应该覆盖你的Car
的Equals
-方法
【讨论】:
以上是关于List.Contains 返回 false,即使它看起来应该返回 true的主要内容,如果未能解决你的问题,请参考以下文章