我正在尝试在我的一个类中使用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
)正常工作。(不是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