我遇到过一种情况,我喜欢比较一个有一个案例的歧视联盟,这个案例不能直接比较,而且我不需要在(自定义)比较中使用。出于这个原因,我写了CustomEquality
和CustomComparison
函数。唉,我得到了一个stackoverflow,一般来说,我不确定如何在F#中处理这种相等覆盖情况。我通过 Don Syme , Chris Smith Equality and Comparison Constraints in F#阅读F# Language Details (Gotchas)。
< edit:正如评论中所指出的那样,对于Funky
案例,应该做些什么?我对How do I create a job queue using a MailboxProcessor?提出了类似的想法,其中我列出了可用于执行功能或控制状态机的DU。
看一下其他帖子(我不在这里制作代码),优雅地使用MailboxProcessor
我看到它有类似的问题和一些类似的想法。我不确定设计是否会更好,或者是否有比较功能的方法,无论如何我还有更多问题(使用C#背景)。
问题:
Equals
中的堆栈溢出? (可能很简单,但是......)IComparable
应该实施吗?static member (=)
等应该超载博客文章?IEquatable
?我认为其中一些可以通过查看IL来回答(例如,如果编译器已经为DUs生成IEquatable
),只是为了确保我没有忽略任何内容。
代码
[<CustomEquality; CustomComparison>]
type FunkyUnion =
| Case1
| Case2
| Funky of (unit -> unit)
override x.Equals(obj) =
//This here will cause a stackoverflow to occur...
match obj with
| :? FunkyUnion as y -> (x = y)
| _ -> false
override x.GetHashCode() =
match x with
| Case1 -> 1
| Case2 -> 2
| _ -> 3
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? FunkyUnion as y -> compare x y
| _ -> invalidArg "yobj" "cannot compare value of different types"
interface System.IComparable<FunkyUnion> with
member x.CompareTo(y) =
compare x y
[<EntryPoint>]
let main argv =
let funky1 = FunkyUnion.Case1
let funky2 = FunkyUnion.Case2
if funky1 = funky2 then
printfn "!!!"
printfn "!"
0
答案 0 :(得分:3)
您在等号中获得了堆栈溢出,因为您正在使用=
与您正在实施Equals
的同一类型。因此Equals
调用=
,=
调用Equals
,依此类推......
您想为Equals
做些什么:
override this.Equals(o) =
match o with
| :? FunkyUnion as fu ->
match this, fu with
| Case1, Case1 | Case2, Case2 -> true
| Funky f1, Funky f2 -> (* whatever you want to do for this case *)
| _, _ -> false
| _ -> false
您可以以类似的方式更新CompareTo。这应该让你开始。