我正在尝试将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))
答案 0 :(得分:4)
这是一个应该有效的实现:
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
答案 1 :(得分:1)
我相信你需要实现IComparer<T>
来设置理解(例如Set.of_list
)才能工作。 (不 IComparable<T>
,虽然我可能错了,但往往使用不太广泛。)
这个blog post解释了如何在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中进行比较时,所有这些界面真的让人感到困惑!)
答案 2 :(得分:1)
关于我对其他答案的评论,您可以将其纳入可重用的基类,但我不确定这是一个好主意:
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