为什么F#没有为operator==提供自定义重载?

7
F#中的联合类型和其他基本类型默认使用结构相等,并提供了一个生成的 .Equals 方法覆盖。F#相等运算符显然与C#不同,即使对于引用类型也使用 .Equals 方法,但是当从C#中使用F#联合类型时,默认的对象operator==会被使用,它检查引用相等而不是结构相等。
为什么F#不为联合类型生成自定义operator==,以便在其他.NET语言中使用==时获得预期的行为?
2个回答

1

我不在F#团队中,所以我只能猜测,但以下是一些可能的原因:

  1. 如果你想在C#中使用结构相等性,你可以直接使用Equals方法。C#提供了测试两种不同类型的相等性的方法——为什么F#要强制它们以相同的方式行事,而有些人可能更喜欢使用引用相等性呢?
  2. 如果你想强制C#使用结构相等性,那么自己实现也很容易:

    type T = A | B of int with
      static member op_Equality(t:T,t2:T) = t = t2
      // or even static member (=)(t:T, t2:T) = t = t2
    
  3. 任何功能都有开发成本,因此即使自动生成op_Equality有明显的好处,也可能会被放弃以支持更高优先级的功能。


是的,但“==”并不总是引用相等,object.ReferenceEquals才是。在C#中,“==”对于有意义的情况(例如字符串,它是一个引用类型,但使用“==”时确实进行值比较)使用值相等。 - SoftMemes
有趣的是,根据反射器(Reflector)的说法,Object.ReferenceEquals 只是调用了 == - Joel Mueller
@Joel - 没问题,因为参数被静态类型化为对象,这意味着接受对象的operator==将始终被使用,即使运行时类型完全不同。 - SoftMemes
@Freed - 我并不完全不同意;我认为两种方法都有优缺点。老实说,我不太喜欢 C# 的 == 运算符的行为方式——很容易错误地退回到引用相等性。我认为使用 Equals 几乎总是更好的选择,对于 F# 类型也可以正常工作。 - kvb

1

这种行为是由您使用的语言而不是您使用的类型的原始语言定义的。


但是毫无疑问,operator==必须被视为.NET概念而不是C#概念,而F#需要与其他.NET兼容。 - SoftMemes
== 操作符是 C# 的东西。它们使用不同的名称 (= vs ==),正是因为它们执行不同的操作,并且这来自 OCaml 继承而来。 - J D
@Jon - 虽然这是正确的,但 F# 团队确保通用算术运算符可以跨语言工作(例如,(+) 被翻译为 op_Addition,这是 C# 可以识别的)。他们同样可以轻易地生成一个 op_Equality 方法。 - kvb
@kvb:你是指 F# 自己的数值类型,比如向量和矩阵吗? - J D
@Jon:不,我的意思是如果你创建了一个定义,例如 type T() = static member (+)(_:T,_:T) = T(),那么你也应该能够在 C# 中对 T 的实例使用 + 运算符。这是因为 F# 编译形式会创建一个名为 op_Addition 的静态方法,这也是 C# 重载 + 运算符的方式。 - kvb
@kvb:我明白了。可能因为它没有替换现有的C#功能,所以被认为是可以接受的。 - J D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接