为什么 F# 中的 CustomEquality 和 CustomComparison 有两种不同的语法?
Why are there two different syntaxes for CustomEquality and CustomComparison in F#?
我想在 F# 中实现一个类型 Symbol
,它有一个关联的字符串和位置(比如文本中的行号)。我会这样做:
type Symbol = Symbol of string * int // (string, line number)
我想要一个消除行号的自定义相等性。我将有一个 "strict equality" 考虑行号,但我希望默认相等性仅比较字符串。看着this SO post,似乎必须做如下:
[<CustomEquality; CustomComparison>]
type Symbol =
| Symbol of string * int
member x.GetString() =
match x with
| Symbol (s, _) -> s
override x.Equals(y) = // Equality only compares strings, not positions.
match y with
| :? Symbol as i -> i.GetString() = x.GetString()
| _ -> false
override x.GetHashCode() =
match x with
| Symbol (s, p) -> hash (s, p)
但是,要实现自定义比较,必须在上面的声明下面添加
interface System.IComparable with
member x.CompareTo(yobj) =
match yobj with
| :? Symbol as y -> compare (x.GetString()) (y.GetString())
| _ -> invalidArg "yobj" "cannot compare values of different types"
为什么我可以写override x.Equals(y)...
,而不能写override x.CompareTo(yobj)...
?为什么我必须指定 interface System.IComparable with ...
?好像有一个System.IEquatable
,但我不需要指定它,为什么?区别不大,但我只是想知道为什么会有区别。
不同之处在于,对于 Equals,您要重写 Object.Equals - 这是基于 class 的虚方法,而对于 CompareTo,您要实现一个接口(在 F# 中需要显式通过 "interface .. with".
实现
我想在 F# 中实现一个类型 Symbol
,它有一个关联的字符串和位置(比如文本中的行号)。我会这样做:
type Symbol = Symbol of string * int // (string, line number)
我想要一个消除行号的自定义相等性。我将有一个 "strict equality" 考虑行号,但我希望默认相等性仅比较字符串。看着this SO post,似乎必须做如下:
[<CustomEquality; CustomComparison>]
type Symbol =
| Symbol of string * int
member x.GetString() =
match x with
| Symbol (s, _) -> s
override x.Equals(y) = // Equality only compares strings, not positions.
match y with
| :? Symbol as i -> i.GetString() = x.GetString()
| _ -> false
override x.GetHashCode() =
match x with
| Symbol (s, p) -> hash (s, p)
但是,要实现自定义比较,必须在上面的声明下面添加
interface System.IComparable with
member x.CompareTo(yobj) =
match yobj with
| :? Symbol as y -> compare (x.GetString()) (y.GetString())
| _ -> invalidArg "yobj" "cannot compare values of different types"
为什么我可以写override x.Equals(y)...
,而不能写override x.CompareTo(yobj)...
?为什么我必须指定 interface System.IComparable with ...
?好像有一个System.IEquatable
,但我不需要指定它,为什么?区别不大,但我只是想知道为什么会有区别。
不同之处在于,对于 Equals,您要重写 Object.Equals - 这是基于 class 的虚方法,而对于 CompareTo,您要实现一个接口(在 F# 中需要显式通过 "interface .. with".
实现