我有一个简单的F#区分联合,它结合了bool,一个字符串和一个浮点数。我想覆盖此联合的Object.Equals(arg),以便在检查浮点相等时我可以放入epsilon来解决精度错误。编译器抱怨说如果我覆盖this.Equals(arg),我也应该重写this.GetHashCode()和this.CompareTo(arg)。对于这些覆盖,我没有计划特殊功能,所以我只想调用这些方法的默认版本。在我的实现中,我有三次调用GetHashCode,并且对我所区分的并集中的每种类型调用CompareTo三次:每种类型一次。
有没有办法只用一次GetHashCode调用就可以对GetHashCode覆盖进行编码? CompareTo的问题是什么?我所区分的联盟中的所有类型都实现了ICompareable。
[<CustomEquality;CustomComparison>]
type MyType =
| Bool of bool
| Str of string
| Float of float
override this.Equals(arg) =
let epsilon = 0.1
match arg with
| :? MyType as other ->
match this, other with
| Bool(a), Bool(b) -> a = b
| Str(a), Str(b) -> a = b
| Float(a), Float(b) -> Math.Abs(a - b) < epsilon
| _ -> false
| _ -> false
override this.GetHashCode() =
match this with
// Three calls to GetHashCode. I'd like only one
| Bool(a) -> a.GetHashCode()
| Str(a) -> a.GetHashCode()
| Float(a) -> a.GetHashCode()
| _ -> 0
interface System.IComparable with
member this.CompareTo arg =
match arg with
| :? MyType as other ->
match this, other with
// Three calls to CompareTo. I'd like only one
| Bool(a), Bool(b) -> a.CompareTo(b)
| Str(a), Str(b) -> a.CompareTo(b)
| Float(a), Float(b) -> a.CompareTo(b)
| _ -> 0
| _ -> 0
答案 0 :(得分:5)
您可以定义一个帮助器属性,将DU的内容提取为obj
:
member this.Value =
match this with
| Bool(b) -> box b
| Str(s) -> box s
| Float(f) -> box f
然后你可以通过获取值来实现GetHashCode
(这涉及一些装箱,所以它会慢一些)并在返回的对象上调用GetHashCode
:
override this.GetHashCode() =
this.Value.GetHashCode()