2009-05-21 10 views
4

私は持っているクラスでSet操作を使用しようとしています。このクラスのすべてのインスタンスには一意のIDがあります。 System.IComparableインターフェイスを実装する必要がありますか?その場合はどうすればよいですか?F#カスタムクラスを使用して設定

type SomeClass(id : int) = 
    member this.ID = id 

let someSet = Set.of_list [SomeClass(1); SomeClass(2)] 
let test = someSet.Contains(SomeClass(2))  

答えて

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 
+0

本当にありがとうございます、アクティブなレコードパターンを実装するF#パワーパックには何かありますか?私がちょうどそれを継承することができれば涼しいだろう。うーん、おそらく私はこのクラスにもっと追加し、そのように使用します。 – bhd739ge

+0

他の回答を参照してください。 – Brian

+0

辞書の代わりに辞書を使うことを考えましたか? – gradbot

1

私はあなたが動作するように設定された内包(例えばSet.of_list)のためIComparer<T>を実装する必要があると考えています。 (あまり広く使用される傾向にあるない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に比較するために、これらすべてのインターフェイスで混乱取得!)

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 
関連する問題