F # Установить с использованием пользовательского класса
Я пытаюсь использовать операции Set с классом, который у меня есть. Каждый экземпляр этого класса имеет уникальный идентификатор. Мне нужно реализовать интерфейс 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))
Ответы
Ответ 1
Вот реализация, которая должна работать:
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
Ответ 2
Я считаю, что вам нужно реализовать 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!)
Ответ 3
Что касается комментария к моему другому ответу, вы можете включить его в многоразовый базовый класс, но я не уверен, что это действительно хорошая идея:
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