我正在嘗試使用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))
我正在嘗試使用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))
下面是應該工作的落實:
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>
,這往往是不太廣泛使用 - 雖然我可能是錯的。)
這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比較!)
關於我的其他答案的評論,你可以計算入可重複使用的基礎這但我不確定它確實是一個好主意:
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
非常感謝,有沒有在F#power pack中實現活動記錄模式的東西?如果我能繼承它,會很酷。嗯,也許我會增加更多的這個類,並使用它。 – bhd739ge 2009-05-22 03:56:51