F# 使用自定义类设置

发布于 2024-07-21 13:15:09 字数 274 浏览 6 评论 0原文

我正在尝试将 Set 操作与我拥有的类一起使用。 该类的每个实例都有一个唯一的 ID。 我是否需要实现 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))    

I'm trying to use Set operations with a class that I have. Every instance of this class has a unique ID. Do I need to implement the System.IComparable interface and if so how would I?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别闹i 2024-07-28 13:15:09

这是一个应该有效的实现:

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

Here's an implementation that should work:

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
思念满溢 2024-07-28 13:15:09

我相信您需要实现 IComparer 才能使集合推导式(例如 Set.of_list)发挥作用。 (不是 IComparable,它的使用往往不太广泛 - 尽管我可能是错的。)

这个 博客文章 一般性地解释了如何在 F# 中实现接口。 它还包括实现 IComparer 的类型的特定示例,这实际上并不像您希望的那样简单。

type Comp() =  
    interface IComparer with  
        member x.Compare(a, b) = 0  
    member x.Compare(a, b) = (x :> IComparer).Compare(a,b)  

让我知道这是否适合您。 我怀疑您实际上可能需要实现 IEqualityComparer,因为据我所知,这就是 LINQ 集扩展方法的基础。 (在 BCL 中进行比较的所有这些接口确实令人困惑!)

I believe you will need to implement IComparer<T> for set comprehensions (e.g. Set.of_list) to work. (Not IComparable<T>, which tends to be less widely used - though I may be wrong.)

This blog post explains in general how to implement interfaces in F#. It also includes a specific example of a type implementing the IComparer<T>, which actually isn't straightforward as you might hope.

type Comp() =  
    interface IComparer with  
        member x.Compare(a, b) = 0  
    member x.Compare(a, b) = (x :> IComparer).Compare(a,b)  

Let me know if the works for you. I have some suspicion that you might in fact need to implement the IEqualityComparer<T> instead, since that's what LINQ set extension methods are based around, as far as I know. (It really gets confusing with all these interfaces for comparing in the BCL!)

独自←快乐 2024-07-28 13:15:09

关于我的其他答案的评论,您可以将其纳入可重用的基类中,但我不确定这真的是一个好主意:

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

Regarding the comment on my other answer, you could factor this into a reusable base class, but I'm not sure it's really a good idea:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文