2009-05-21 82 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#power pack中實現活動記錄模式的東西?如果我能繼承它,會很酷。嗯,也許我會增加更多的這個類,並使用它。 – bhd739ge 2009-05-22 03:56:51

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比較!)

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