为什么这两个相同类型的F#类对象不相等?

f#

有人可以向我解释为什么这两个对象不相等,处理此类问题的解决方案是什么?

[<AllowNullLiteralAttribute>]
type Duration (id, startDate, endDate) =
    
    member val DbId : string = id with get,set
    member val StartDate : Nullable<DateTime> = startDate with get,set
    member val EndDate : Nullable<DateTime> = endDate with get,set

    new () =
        Duration(null, System.Nullable(), System.Nullable())

[<AllowNullLiteralAttribute>]
type ProductMedium (mediumType, fileLink, duration) =
    member val MediumType : string = mediumType with get,set
    member val FileLink : string = fileLink with get,set
    member val Duration : Duration = duration with get,set

    new () =
        ProductMedium (null, null, null)

let medium1 = new ProductMedium("Type1", null, null)
let medium2 = new ProductMedium("Type1", null, null)

medium1 = medium2 // returns false

回答

这就是 .NET 中的相等性的工作原理:默认情况下,除非您自己实现比较方法,否则相等性是“通过引用”的——也就是说,每个对象只与自身相等,不与其他任何对象相等。

对于许多标准库类型,例如字符串,实际上已经实现了比较方法。这就是为什么相等的字符串是相等的,即使它们不是同一个对象。但是对于您自己滚动的类型,您必须按照您认为合适的方式实现比较方法。

对于您在这里尝试做的事情,您想要的方法是Equals. 这是System.Object类型上的虚拟方法,默认情况下它按上述方式工作:每个对象仅等于自身。但是您可以为您的类型覆盖它:

type ProductMedium (mediumType, fileLink, duration) =
    member val MediumType : string = mediumType with get,set
    member val FileLink : string = fileLink with get,set
    member val Duration : string = duration with get,set

    override this.Equals(other) = 
      match other with
      | :? ProductMedium as p -> 
          this.MediumType = p.MediumType && this.FileLink = p.FileLink && this.Duration = p.Duration
      | _ ->
          false

现在比较将按照您期望的方式进行。但是您也会收到警告,要求您也实施GetHashCode。这是因为 .NET 库中的许多标准容器(例如DictionaryHashtable)期望相等的对象也具有相同的散列,如果您的对象不这样做,则可能无法正常工作。我将把实现GetHashCode作为练习。有关更多信息,请参阅文档。


但是由于您使用的是 F#,实际上您有一个更好的选择:不要使用常规的 .NET 类,而是使用 F# 记录:

type ProductMedium = { MediumType : string; FileLink : string; Duration : string }

let medium1 = { MediumType = "Type1"; FileLink = null; Duration = null }
let medium2 = { MediumType = "Type2"; FileLink = null; Duration = null }

默认情况下,F# 记录具有“结构相等”(即,当所有字段相等时,两个记录相等),由编译器为您实现,但它们也提供其他好处,例如更短的语法、默认不变性、功能更新语法、模式匹配、类型推断等。强烈推荐。


以上是为什么这两个相同类型的F#类对象不相等?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>