مجموعة F # باستخدام فئة مخصصة
-
23-08-2019 - |
سؤال
أحاول استخدام عمليات تعيين مع فئة لدي. كل مثيل من هذه الفئة له معرف فريد. هل أحتاج إلى تطبيق نظام النظام.
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>
, ، والتي تميل إلى أن تكون أقل استخداما على نطاق واسع - على الرغم من أنني قد أكون مخطئا.)
هذه مشاركة مدونة يشرح بشكل عام كيفية تنفيذ واجهات في 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