4

我正在尝试将 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))    
4

3 回答 3

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
于 2009-05-21T23:50:50.953 回答
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 中进行比较的所有这些接口真的让人感到困惑!)

于 2009-05-21T23:37:46.190 回答
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
于 2009-05-22T11:41:20.527 回答