我正在尝试将 Set 操作与我拥有的类一起使用。此类的每个实例都有一个唯一的 ID。我是否需要实现 System.IComparable 接口,如果需要,我该怎么做?
type SomeClass(id : int) =
member this.ID = id
let someSet = Set.of_list [SomeClass(1); SomeClass(2)]
let test = someSet.Contains(SomeClass(2))
我正在尝试将 Set 操作与我拥有的类一起使用。此类的每个实例都有一个唯一的 ID。我是否需要实现 System.IComparable 接口,如果需要,我该怎么做?
type SomeClass(id : int) =
member this.ID = id
let someSet = Set.of_list [SomeClass(1); SomeClass(2)]
let test = someSet.Contains(SomeClass(2))
这是一个应该有效的实现:
type SomeClass(id : int) =
member this.ID = id
override this.Equals(o) =
match o with
| :? SomeClass as sc -> this.ID = sc.ID
| _ -> false
override this.GetHashCode() =
id.GetHashCode()
interface System.IComparable with
member this.CompareTo(o) =
match o with
| :? SomeClass as sc -> compare this.ID sc.ID
| _ -> -1
我相信你需要实现IComparer<T>
集合理解(例如Set.of_list
)才能工作。(Not IComparable<T>
,这往往不太广泛使用 - 尽管我可能是错的。)
这篇博文大体上解释了如何在 F# 中实现接口。它还包括一个实现 的类型的具体示例IComparer<T>
,这实际上并不像您希望的那样简单。
type Comp() =
interface IComparer with
member x.Compare(a, b) = 0
member x.Compare(a, b) = (x :> IComparer).Compare(a,b)
让我知道是否适合您。我怀疑您实际上可能需要实现IEqualityComparer<T>
,因为据我所知,这是 LINQ 集扩展方法所基于的。(在 BCL 中进行比较的所有这些接口真的让人感到困惑!)
关于对我的其他答案的评论,您可以将其纳入可重用的基类,但我不确定这是否真的是一个好主意:
type EqCompBase<'EqKey,
'DerivedType when 'DerivedType :> EqCompBase<'EqKey,'DerivedType> >
(id : 'EqKey) =
member this.ID = id
override this.Equals(o) =
match o with
| :? EqCompBase<'EqKey, 'DerivedType> as sc -> this.ID = sc.ID
| _ -> false
override this.GetHashCode() =
id.GetHashCode()
interface System.IComparable with
member this.CompareTo(o) =
match o with
| :? EqCompBase<'EqKey, 'DerivedType> as sc -> compare this.ID sc.ID
| _ -> -1
type SomeClass(id : int, otherFieldThatDoesNotMatterForEquality : string) =
inherit EqCompBase<int, SomeClass>(id)
let someSet = Set.of_list [SomeClass(1,"yadda"); SomeClass(2,"blah")]
let test = someSet.Contains(SomeClass(2,"foo"))
printfn "%A" test // true