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 检查是否有任何列表项与您提供的参数一样指向同一个对象。而不是这两个对象在逻辑上是否相等。

如果你想让它这样做,你应该覆盖你的CarEquals-方法

【讨论】:

以上是关于List.Contains 返回 false,即使它看起来应该返回 true的主要内容,如果未能解决你的问题,请参考以下文章

如何判断List<String>list中是不是包含某个字符串

Java-List元素判断

Java-List元素判断

FileExists() 返回 false,即使文件存在

即使应该返回 false,循环也会返回 true

即使注册成功,isRegisteredForRemoteNotifications 也会返回 false