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)が機能するためには、実装する必要があると思います。(そう 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 に答える